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<'a>(
 5744        &'a self,
 5745        cx: &'a AppContext,
 5746    ) -> Option<impl 'a + Iterator<Item = Range<OffsetUtf16>>> {
 5747        let snapshot = self.buffer.read(cx).read(cx);
 5748        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 5749        Some(ranges.into_iter().map(move |range| {
 5750            range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 5751        }))
 5752    }
 5753}
 5754
 5755impl EditorSnapshot {
 5756    pub fn is_focused(&self) -> bool {
 5757        self.is_focused
 5758    }
 5759
 5760    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5761        self.placeholder_text.as_ref()
 5762    }
 5763
 5764    pub fn scroll_position(&self) -> Vector2F {
 5765        compute_scroll_position(
 5766            &self.display_snapshot,
 5767            self.scroll_position,
 5768            &self.scroll_top_anchor,
 5769        )
 5770    }
 5771}
 5772
 5773impl Deref for EditorSnapshot {
 5774    type Target = DisplaySnapshot;
 5775
 5776    fn deref(&self) -> &Self::Target {
 5777        &self.display_snapshot
 5778    }
 5779}
 5780
 5781fn compute_scroll_position(
 5782    snapshot: &DisplaySnapshot,
 5783    mut scroll_position: Vector2F,
 5784    scroll_top_anchor: &Anchor,
 5785) -> Vector2F {
 5786    if *scroll_top_anchor != Anchor::min() {
 5787        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5788        scroll_position.set_y(scroll_top + scroll_position.y());
 5789    } else {
 5790        scroll_position.set_y(0.);
 5791    }
 5792    scroll_position
 5793}
 5794
 5795#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5796pub enum Event {
 5797    Activate,
 5798    BufferEdited,
 5799    Edited,
 5800    Reparsed,
 5801    Blurred,
 5802    DirtyChanged,
 5803    Saved,
 5804    TitleChanged,
 5805    SelectionsChanged { local: bool },
 5806    ScrollPositionChanged { local: bool },
 5807    Closed,
 5808    IgnoredInput,
 5809}
 5810
 5811pub struct EditorFocused(pub ViewHandle<Editor>);
 5812pub struct EditorBlurred(pub ViewHandle<Editor>);
 5813pub struct EditorReleased(pub WeakViewHandle<Editor>);
 5814
 5815impl Entity for Editor {
 5816    type Event = Event;
 5817
 5818    fn release(&mut self, cx: &mut MutableAppContext) {
 5819        cx.emit_global(EditorReleased(self.handle.clone()));
 5820    }
 5821}
 5822
 5823impl View for Editor {
 5824    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 5825        let style = self.style(cx);
 5826        let font_changed = self.display_map.update(cx, |map, cx| {
 5827            map.set_font(style.text.font_id, style.text.font_size, cx)
 5828        });
 5829
 5830        if font_changed {
 5831            let handle = self.handle.clone();
 5832            cx.defer(move |cx| {
 5833                if let Some(editor) = handle.upgrade(cx) {
 5834                    editor.update(cx, |editor, cx| {
 5835                        hide_hover(editor, cx);
 5836                    })
 5837                }
 5838            });
 5839        }
 5840
 5841        Stack::new()
 5842            .with_child(
 5843                EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed(),
 5844            )
 5845            .with_child(ChildView::new(&self.mouse_context_menu).boxed())
 5846            .boxed()
 5847    }
 5848
 5849    fn ui_name() -> &'static str {
 5850        "Editor"
 5851    }
 5852
 5853    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 5854        let focused_event = EditorFocused(cx.handle());
 5855        cx.emit_global(focused_event);
 5856        if let Some(rename) = self.pending_rename.as_ref() {
 5857            cx.focus(&rename.editor);
 5858        } else {
 5859            self.focused = true;
 5860            self.blink_cursors(self.blink_epoch, cx);
 5861            self.buffer.update(cx, |buffer, cx| {
 5862                buffer.finalize_last_transaction(cx);
 5863                if self.leader_replica_id.is_none() {
 5864                    buffer.set_active_selections(
 5865                        &self.selections.disjoint_anchors(),
 5866                        self.selections.line_mode,
 5867                        cx,
 5868                    );
 5869                }
 5870            });
 5871        }
 5872    }
 5873
 5874    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 5875        let blurred_event = EditorBlurred(cx.handle());
 5876        cx.emit_global(blurred_event);
 5877        self.focused = false;
 5878        self.buffer
 5879            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 5880        self.hide_context_menu(cx);
 5881        hide_hover(self, cx);
 5882        cx.emit(Event::Blurred);
 5883        cx.notify();
 5884    }
 5885
 5886    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 5887        let mut context = Self::default_keymap_context();
 5888        let mode = match self.mode {
 5889            EditorMode::SingleLine => "single_line",
 5890            EditorMode::AutoHeight { .. } => "auto_height",
 5891            EditorMode::Full => "full",
 5892        };
 5893        context.map.insert("mode".into(), mode.into());
 5894        if self.pending_rename.is_some() {
 5895            context.set.insert("renaming".into());
 5896        }
 5897        match self.context_menu.as_ref() {
 5898            Some(ContextMenu::Completions(_)) => {
 5899                context.set.insert("showing_completions".into());
 5900            }
 5901            Some(ContextMenu::CodeActions(_)) => {
 5902                context.set.insert("showing_code_actions".into());
 5903            }
 5904            None => {}
 5905        }
 5906
 5907        for layer in self.keymap_context_layers.values() {
 5908            context.extend(layer);
 5909        }
 5910
 5911        context
 5912    }
 5913
 5914    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
 5915        Some(
 5916            self.buffer
 5917                .read(cx)
 5918                .read(cx)
 5919                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 5920                .collect(),
 5921        )
 5922    }
 5923
 5924    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 5925        // Prevent the IME menu from appearing when holding down an alphabetic key
 5926        // while input is disabled.
 5927        if !self.input_enabled {
 5928            return None;
 5929        }
 5930
 5931        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 5932        Some(range.start.0..range.end.0)
 5933    }
 5934
 5935    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 5936        let range = self.marked_text_ranges(cx)?.next()?;
 5937        Some(range.start.0..range.end.0)
 5938    }
 5939
 5940    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 5941        self.clear_text_highlights::<InputComposition>(cx);
 5942        self.ime_transaction.take();
 5943    }
 5944
 5945    fn replace_text_in_range(
 5946        &mut self,
 5947        range_utf16: Option<Range<usize>>,
 5948        text: &str,
 5949        cx: &mut ViewContext<Self>,
 5950    ) {
 5951        if !self.input_enabled {
 5952            cx.emit(Event::IgnoredInput);
 5953            return;
 5954        }
 5955
 5956        self.transact(cx, |this, cx| {
 5957            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 5958                let selected_range = this.selected_text_range(cx).unwrap();
 5959                let start_delta = range_utf16.start as isize - selected_range.start as isize;
 5960                let end_delta = range_utf16.end as isize - selected_range.end as isize;
 5961                Some(
 5962                    this.selections
 5963                        .all::<OffsetUtf16>(cx)
 5964                        .into_iter()
 5965                        .map(|mut selection| {
 5966                            selection.start.0 =
 5967                                (selection.start.0 as isize).saturating_add(start_delta) as usize;
 5968                            selection.end.0 =
 5969                                (selection.end.0 as isize).saturating_add(end_delta) as usize;
 5970                            selection.start..selection.end
 5971                        })
 5972                        .collect::<Vec<_>>(),
 5973                )
 5974            } else if let Some(marked_ranges) = this.marked_text_ranges(cx) {
 5975                Some(marked_ranges.collect())
 5976            } else {
 5977                None
 5978            };
 5979
 5980            if let Some(new_selected_ranges) = new_selected_ranges {
 5981                this.change_selections(None, cx, |selections| {
 5982                    selections.select_ranges(new_selected_ranges)
 5983                });
 5984            }
 5985            this.handle_input(text, cx);
 5986        });
 5987
 5988        if let Some(transaction) = self.ime_transaction {
 5989            self.buffer.update(cx, |buffer, cx| {
 5990                buffer.group_until_transaction(transaction, cx);
 5991            });
 5992        }
 5993
 5994        self.unmark_text(cx);
 5995    }
 5996
 5997    fn replace_and_mark_text_in_range(
 5998        &mut self,
 5999        range_utf16: Option<Range<usize>>,
 6000        text: &str,
 6001        new_selected_range_utf16: Option<Range<usize>>,
 6002        cx: &mut ViewContext<Self>,
 6003    ) {
 6004        if !self.input_enabled {
 6005            cx.emit(Event::IgnoredInput);
 6006            return;
 6007        }
 6008
 6009        let transaction = self.transact(cx, |this, cx| {
 6010            let ranges_to_replace = if let Some(marked_ranges) = this.marked_text_ranges(cx) {
 6011                let mut marked_ranges = marked_ranges.collect::<Vec<_>>();
 6012                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 6013                    for marked_range in &mut marked_ranges {
 6014                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 6015                        marked_range.start.0 += relative_range_utf16.start;
 6016                    }
 6017                }
 6018                Some(marked_ranges)
 6019            } else if let Some(range_utf16) = range_utf16 {
 6020                let selected_range = this.selected_text_range(cx).unwrap();
 6021                let start_delta = range_utf16.start as isize - selected_range.start as isize;
 6022                let end_delta = range_utf16.end as isize - selected_range.end as isize;
 6023                Some(
 6024                    this.selections
 6025                        .all::<OffsetUtf16>(cx)
 6026                        .into_iter()
 6027                        .map(|mut selection| {
 6028                            selection.start.0 =
 6029                                (selection.start.0 as isize).saturating_add(start_delta) as usize;
 6030                            selection.end.0 =
 6031                                (selection.end.0 as isize).saturating_add(end_delta) as usize;
 6032                            selection.start..selection.end
 6033                        })
 6034                        .collect::<Vec<_>>(),
 6035                )
 6036            } else {
 6037                None
 6038            };
 6039
 6040            if let Some(ranges) = ranges_to_replace {
 6041                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 6042            }
 6043
 6044            let marked_ranges = {
 6045                let snapshot = this.buffer.read(cx).read(cx);
 6046                this.selections
 6047                    .disjoint_anchors()
 6048                    .into_iter()
 6049                    .map(|selection| {
 6050                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 6051                    })
 6052                    .collect::<Vec<_>>()
 6053            };
 6054
 6055            if text.is_empty() {
 6056                this.unmark_text(cx);
 6057            } else {
 6058                this.highlight_text::<InputComposition>(
 6059                    marked_ranges.clone(),
 6060                    this.style(cx).composition_mark,
 6061                    cx,
 6062                );
 6063            }
 6064
 6065            this.handle_input(text, cx);
 6066
 6067            if let Some(new_selected_range) = new_selected_range_utf16 {
 6068                let snapshot = this.buffer.read(cx).read(cx);
 6069                let new_selected_ranges = marked_ranges
 6070                    .into_iter()
 6071                    .map(|marked_range| {
 6072                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 6073                        OffsetUtf16(new_selected_range.start + insertion_start)
 6074                            ..OffsetUtf16(new_selected_range.end + insertion_start)
 6075                    })
 6076                    .collect::<Vec<_>>();
 6077
 6078                drop(snapshot);
 6079                this.change_selections(None, cx, |selections| {
 6080                    selections.select_ranges(new_selected_ranges)
 6081                });
 6082            }
 6083        });
 6084
 6085        self.ime_transaction = self.ime_transaction.or(transaction);
 6086        if let Some(transaction) = self.ime_transaction {
 6087            self.buffer.update(cx, |buffer, cx| {
 6088                buffer.group_until_transaction(transaction, cx);
 6089            });
 6090        }
 6091
 6092        if self.text_highlights::<InputComposition>(cx).is_none() {
 6093            self.ime_transaction.take();
 6094        }
 6095    }
 6096}
 6097
 6098fn build_style(
 6099    settings: &Settings,
 6100    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6101    override_text_style: Option<&OverrideTextStyle>,
 6102    cx: &AppContext,
 6103) -> EditorStyle {
 6104    let font_cache = cx.font_cache();
 6105
 6106    let mut theme = settings.theme.editor.clone();
 6107    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6108        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6109        theme.text_color = field_editor_theme.text.color;
 6110        theme.selection = field_editor_theme.selection;
 6111        theme.background = field_editor_theme
 6112            .container
 6113            .background_color
 6114            .unwrap_or_default();
 6115        EditorStyle {
 6116            text: field_editor_theme.text,
 6117            placeholder_text: field_editor_theme.placeholder_text,
 6118            theme,
 6119        }
 6120    } else {
 6121        let font_family_id = settings.buffer_font_family;
 6122        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6123        let font_properties = Default::default();
 6124        let font_id = font_cache
 6125            .select_font(font_family_id, &font_properties)
 6126            .unwrap();
 6127        let font_size = settings.buffer_font_size;
 6128        EditorStyle {
 6129            text: TextStyle {
 6130                color: settings.theme.editor.text_color,
 6131                font_family_name,
 6132                font_family_id,
 6133                font_id,
 6134                font_size,
 6135                font_properties,
 6136                underline: Default::default(),
 6137            },
 6138            placeholder_text: None,
 6139            theme,
 6140        }
 6141    };
 6142
 6143    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6144        if let Some(highlighted) = style
 6145            .text
 6146            .clone()
 6147            .highlight(highlight_style, font_cache)
 6148            .log_err()
 6149        {
 6150            style.text = highlighted;
 6151        }
 6152    }
 6153
 6154    style
 6155}
 6156
 6157trait SelectionExt {
 6158    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6159    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6160    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6161    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6162        -> Range<u32>;
 6163}
 6164
 6165impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6166    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6167        let start = self.start.to_point(buffer);
 6168        let end = self.end.to_point(buffer);
 6169        if self.reversed {
 6170            end..start
 6171        } else {
 6172            start..end
 6173        }
 6174    }
 6175
 6176    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6177        let start = self.start.to_offset(buffer);
 6178        let end = self.end.to_offset(buffer);
 6179        if self.reversed {
 6180            end..start
 6181        } else {
 6182            start..end
 6183        }
 6184    }
 6185
 6186    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6187        let start = self
 6188            .start
 6189            .to_point(&map.buffer_snapshot)
 6190            .to_display_point(map);
 6191        let end = self
 6192            .end
 6193            .to_point(&map.buffer_snapshot)
 6194            .to_display_point(map);
 6195        if self.reversed {
 6196            end..start
 6197        } else {
 6198            start..end
 6199        }
 6200    }
 6201
 6202    fn spanned_rows(
 6203        &self,
 6204        include_end_if_at_line_start: bool,
 6205        map: &DisplaySnapshot,
 6206    ) -> Range<u32> {
 6207        let start = self.start.to_point(&map.buffer_snapshot);
 6208        let mut end = self.end.to_point(&map.buffer_snapshot);
 6209        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6210            end.row -= 1;
 6211        }
 6212
 6213        let buffer_start = map.prev_line_boundary(start).0;
 6214        let buffer_end = map.next_line_boundary(end).0;
 6215        buffer_start.row..buffer_end.row + 1
 6216    }
 6217}
 6218
 6219impl<T: InvalidationRegion> InvalidationStack<T> {
 6220    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6221    where
 6222        S: Clone + ToOffset,
 6223    {
 6224        while let Some(region) = self.last() {
 6225            let all_selections_inside_invalidation_ranges =
 6226                if selections.len() == region.ranges().len() {
 6227                    selections
 6228                        .iter()
 6229                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6230                        .all(|(selection, invalidation_range)| {
 6231                            let head = selection.head().to_offset(&buffer);
 6232                            invalidation_range.start <= head && invalidation_range.end >= head
 6233                        })
 6234                } else {
 6235                    false
 6236                };
 6237
 6238            if all_selections_inside_invalidation_ranges {
 6239                break;
 6240            } else {
 6241                self.pop();
 6242            }
 6243        }
 6244    }
 6245}
 6246
 6247impl<T> Default for InvalidationStack<T> {
 6248    fn default() -> Self {
 6249        Self(Default::default())
 6250    }
 6251}
 6252
 6253impl<T> Deref for InvalidationStack<T> {
 6254    type Target = Vec<T>;
 6255
 6256    fn deref(&self) -> &Self::Target {
 6257        &self.0
 6258    }
 6259}
 6260
 6261impl<T> DerefMut for InvalidationStack<T> {
 6262    fn deref_mut(&mut self) -> &mut Self::Target {
 6263        &mut self.0
 6264    }
 6265}
 6266
 6267impl InvalidationRegion for BracketPairState {
 6268    fn ranges(&self) -> &[Range<Anchor>] {
 6269        &self.ranges
 6270    }
 6271}
 6272
 6273impl InvalidationRegion for SnippetState {
 6274    fn ranges(&self) -> &[Range<Anchor>] {
 6275        &self.ranges[self.active_index]
 6276    }
 6277}
 6278
 6279impl Deref for EditorStyle {
 6280    type Target = theme::Editor;
 6281
 6282    fn deref(&self) -> &Self::Target {
 6283        &self.theme
 6284    }
 6285}
 6286
 6287pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6288    let mut highlighted_lines = Vec::new();
 6289    for line in diagnostic.message.lines() {
 6290        highlighted_lines.push(highlight_diagnostic_message(line));
 6291    }
 6292
 6293    Arc::new(move |cx: &mut BlockContext| {
 6294        let settings = cx.global::<Settings>();
 6295        let theme = &settings.theme.editor;
 6296        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6297        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6298        Flex::column()
 6299            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6300                Label::new(
 6301                    line.clone(),
 6302                    style.message.clone().with_font_size(font_size),
 6303                )
 6304                .with_highlights(highlights.clone())
 6305                .contained()
 6306                .with_margin_left(cx.anchor_x)
 6307                .boxed()
 6308            }))
 6309            .aligned()
 6310            .left()
 6311            .boxed()
 6312    })
 6313}
 6314
 6315pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6316    let mut message_without_backticks = String::new();
 6317    let mut prev_offset = 0;
 6318    let mut inside_block = false;
 6319    let mut highlights = Vec::new();
 6320    for (match_ix, (offset, _)) in message
 6321        .match_indices('`')
 6322        .chain([(message.len(), "")])
 6323        .enumerate()
 6324    {
 6325        message_without_backticks.push_str(&message[prev_offset..offset]);
 6326        if inside_block {
 6327            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6328        }
 6329
 6330        inside_block = !inside_block;
 6331        prev_offset = offset + 1;
 6332    }
 6333
 6334    (message_without_backticks, highlights)
 6335}
 6336
 6337pub fn diagnostic_style(
 6338    severity: DiagnosticSeverity,
 6339    valid: bool,
 6340    theme: &theme::Editor,
 6341) -> DiagnosticStyle {
 6342    match (severity, valid) {
 6343        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6344        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6345        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6346        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6347        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6348        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6349        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6350        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6351        _ => theme.invalid_hint_diagnostic.clone(),
 6352    }
 6353}
 6354
 6355pub fn combine_syntax_and_fuzzy_match_highlights(
 6356    text: &str,
 6357    default_style: HighlightStyle,
 6358    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6359    match_indices: &[usize],
 6360) -> Vec<(Range<usize>, HighlightStyle)> {
 6361    let mut result = Vec::new();
 6362    let mut match_indices = match_indices.iter().copied().peekable();
 6363
 6364    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6365    {
 6366        syntax_highlight.weight = None;
 6367
 6368        // Add highlights for any fuzzy match characters before the next
 6369        // syntax highlight range.
 6370        while let Some(&match_index) = match_indices.peek() {
 6371            if match_index >= range.start {
 6372                break;
 6373            }
 6374            match_indices.next();
 6375            let end_index = char_ix_after(match_index, text);
 6376            let mut match_style = default_style;
 6377            match_style.weight = Some(fonts::Weight::BOLD);
 6378            result.push((match_index..end_index, match_style));
 6379        }
 6380
 6381        if range.start == usize::MAX {
 6382            break;
 6383        }
 6384
 6385        // Add highlights for any fuzzy match characters within the
 6386        // syntax highlight range.
 6387        let mut offset = range.start;
 6388        while let Some(&match_index) = match_indices.peek() {
 6389            if match_index >= range.end {
 6390                break;
 6391            }
 6392
 6393            match_indices.next();
 6394            if match_index > offset {
 6395                result.push((offset..match_index, syntax_highlight));
 6396            }
 6397
 6398            let mut end_index = char_ix_after(match_index, text);
 6399            while let Some(&next_match_index) = match_indices.peek() {
 6400                if next_match_index == end_index && next_match_index < range.end {
 6401                    end_index = char_ix_after(next_match_index, text);
 6402                    match_indices.next();
 6403                } else {
 6404                    break;
 6405                }
 6406            }
 6407
 6408            let mut match_style = syntax_highlight;
 6409            match_style.weight = Some(fonts::Weight::BOLD);
 6410            result.push((match_index..end_index, match_style));
 6411            offset = end_index;
 6412        }
 6413
 6414        if offset < range.end {
 6415            result.push((offset..range.end, syntax_highlight));
 6416        }
 6417    }
 6418
 6419    fn char_ix_after(ix: usize, text: &str) -> usize {
 6420        ix + text[ix..].chars().next().unwrap().len_utf8()
 6421    }
 6422
 6423    result
 6424}
 6425
 6426pub fn styled_runs_for_code_label<'a>(
 6427    label: &'a CodeLabel,
 6428    syntax_theme: &'a theme::SyntaxTheme,
 6429) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6430    let fade_out = HighlightStyle {
 6431        fade_out: Some(0.35),
 6432        ..Default::default()
 6433    };
 6434
 6435    let mut prev_end = label.filter_range.end;
 6436    label
 6437        .runs
 6438        .iter()
 6439        .enumerate()
 6440        .flat_map(move |(ix, (range, highlight_id))| {
 6441            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6442                style
 6443            } else {
 6444                return Default::default();
 6445            };
 6446            let mut muted_style = style.clone();
 6447            muted_style.highlight(fade_out);
 6448
 6449            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6450            if range.start >= label.filter_range.end {
 6451                if range.start > prev_end {
 6452                    runs.push((prev_end..range.start, fade_out));
 6453                }
 6454                runs.push((range.clone(), muted_style));
 6455            } else if range.end <= label.filter_range.end {
 6456                runs.push((range.clone(), style));
 6457            } else {
 6458                runs.push((range.start..label.filter_range.end, style));
 6459                runs.push((label.filter_range.end..range.end, muted_style));
 6460            }
 6461            prev_end = cmp::max(prev_end, range.end);
 6462
 6463            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6464                runs.push((prev_end..label.text.len(), fade_out));
 6465            }
 6466
 6467            runs
 6468        })
 6469}
 6470
 6471#[cfg(test)]
 6472mod tests {
 6473    use crate::test::{
 6474        assert_text_with_selections, build_editor, select_ranges, EditorLspTestContext,
 6475        EditorTestContext,
 6476    };
 6477
 6478    use super::*;
 6479    use futures::StreamExt;
 6480    use gpui::{
 6481        geometry::rect::RectF,
 6482        platform::{WindowBounds, WindowOptions},
 6483    };
 6484    use indoc::indoc;
 6485    use language::{FakeLspAdapter, LanguageConfig};
 6486    use project::FakeFs;
 6487    use settings::EditorSettings;
 6488    use std::{cell::RefCell, rc::Rc, time::Instant};
 6489    use text::Point;
 6490    use unindent::Unindent;
 6491    use util::{
 6492        assert_set_eq,
 6493        test::{
 6494            marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker,
 6495        },
 6496    };
 6497    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6498
 6499    #[gpui::test]
 6500    fn test_edit_events(cx: &mut MutableAppContext) {
 6501        cx.set_global(Settings::test(cx));
 6502        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6503
 6504        let events = Rc::new(RefCell::new(Vec::new()));
 6505        let (_, editor1) = cx.add_window(Default::default(), {
 6506            let events = events.clone();
 6507            |cx| {
 6508                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6509                    if matches!(
 6510                        event,
 6511                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6512                    ) {
 6513                        events.borrow_mut().push(("editor1", *event));
 6514                    }
 6515                })
 6516                .detach();
 6517                Editor::for_buffer(buffer.clone(), None, cx)
 6518            }
 6519        });
 6520        let (_, editor2) = cx.add_window(Default::default(), {
 6521            let events = events.clone();
 6522            |cx| {
 6523                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6524                    if matches!(
 6525                        event,
 6526                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6527                    ) {
 6528                        events.borrow_mut().push(("editor2", *event));
 6529                    }
 6530                })
 6531                .detach();
 6532                Editor::for_buffer(buffer.clone(), None, cx)
 6533            }
 6534        });
 6535        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6536
 6537        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6538        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6539        assert_eq!(
 6540            mem::take(&mut *events.borrow_mut()),
 6541            [
 6542                ("editor1", Event::Edited),
 6543                ("editor1", Event::BufferEdited),
 6544                ("editor2", Event::BufferEdited),
 6545                ("editor1", Event::DirtyChanged),
 6546                ("editor2", Event::DirtyChanged)
 6547            ]
 6548        );
 6549
 6550        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6551        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6552        assert_eq!(
 6553            mem::take(&mut *events.borrow_mut()),
 6554            [
 6555                ("editor2", Event::Edited),
 6556                ("editor1", Event::BufferEdited),
 6557                ("editor2", Event::BufferEdited),
 6558            ]
 6559        );
 6560
 6561        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6562        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6563        assert_eq!(
 6564            mem::take(&mut *events.borrow_mut()),
 6565            [
 6566                ("editor1", Event::Edited),
 6567                ("editor1", Event::BufferEdited),
 6568                ("editor2", Event::BufferEdited),
 6569                ("editor1", Event::DirtyChanged),
 6570                ("editor2", Event::DirtyChanged),
 6571            ]
 6572        );
 6573
 6574        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6575        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6576        assert_eq!(
 6577            mem::take(&mut *events.borrow_mut()),
 6578            [
 6579                ("editor1", Event::Edited),
 6580                ("editor1", Event::BufferEdited),
 6581                ("editor2", Event::BufferEdited),
 6582                ("editor1", Event::DirtyChanged),
 6583                ("editor2", Event::DirtyChanged),
 6584            ]
 6585        );
 6586
 6587        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6588        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6589        assert_eq!(
 6590            mem::take(&mut *events.borrow_mut()),
 6591            [
 6592                ("editor2", Event::Edited),
 6593                ("editor1", Event::BufferEdited),
 6594                ("editor2", Event::BufferEdited),
 6595                ("editor1", Event::DirtyChanged),
 6596                ("editor2", Event::DirtyChanged),
 6597            ]
 6598        );
 6599
 6600        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6601        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6602        assert_eq!(
 6603            mem::take(&mut *events.borrow_mut()),
 6604            [
 6605                ("editor2", Event::Edited),
 6606                ("editor1", Event::BufferEdited),
 6607                ("editor2", Event::BufferEdited),
 6608                ("editor1", Event::DirtyChanged),
 6609                ("editor2", Event::DirtyChanged),
 6610            ]
 6611        );
 6612
 6613        // No event is emitted when the mutation is a no-op.
 6614        editor2.update(cx, |editor, cx| {
 6615            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6616
 6617            editor.backspace(&Backspace, cx);
 6618        });
 6619        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6620    }
 6621
 6622    #[gpui::test]
 6623    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6624        cx.set_global(Settings::test(cx));
 6625        let mut now = Instant::now();
 6626        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6627        let group_interval = buffer.read(cx).transaction_group_interval();
 6628        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6629        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6630
 6631        editor.update(cx, |editor, cx| {
 6632            editor.start_transaction_at(now, cx);
 6633            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6634
 6635            editor.insert("cd", cx);
 6636            editor.end_transaction_at(now, cx);
 6637            assert_eq!(editor.text(cx), "12cd56");
 6638            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6639
 6640            editor.start_transaction_at(now, cx);
 6641            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6642            editor.insert("e", cx);
 6643            editor.end_transaction_at(now, cx);
 6644            assert_eq!(editor.text(cx), "12cde6");
 6645            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6646
 6647            now += group_interval + Duration::from_millis(1);
 6648            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6649
 6650            // Simulate an edit in another editor
 6651            buffer.update(cx, |buffer, cx| {
 6652                buffer.start_transaction_at(now, cx);
 6653                buffer.edit([(0..1, "a")], cx);
 6654                buffer.edit([(1..1, "b")], cx);
 6655                buffer.end_transaction_at(now, cx);
 6656            });
 6657
 6658            assert_eq!(editor.text(cx), "ab2cde6");
 6659            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6660
 6661            // Last transaction happened past the group interval in a different editor.
 6662            // Undo it individually and don't restore selections.
 6663            editor.undo(&Undo, cx);
 6664            assert_eq!(editor.text(cx), "12cde6");
 6665            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6666
 6667            // First two transactions happened within the group interval in this editor.
 6668            // Undo them together and restore selections.
 6669            editor.undo(&Undo, cx);
 6670            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6671            assert_eq!(editor.text(cx), "123456");
 6672            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6673
 6674            // Redo the first two transactions together.
 6675            editor.redo(&Redo, cx);
 6676            assert_eq!(editor.text(cx), "12cde6");
 6677            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6678
 6679            // Redo the last transaction on its own.
 6680            editor.redo(&Redo, cx);
 6681            assert_eq!(editor.text(cx), "ab2cde6");
 6682            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6683
 6684            // Test empty transactions.
 6685            editor.start_transaction_at(now, cx);
 6686            editor.end_transaction_at(now, cx);
 6687            editor.undo(&Undo, cx);
 6688            assert_eq!(editor.text(cx), "12cde6");
 6689        });
 6690    }
 6691
 6692    #[gpui::test]
 6693    fn test_ime_composition(cx: &mut MutableAppContext) {
 6694        cx.set_global(Settings::test(cx));
 6695        let buffer = cx.add_model(|cx| {
 6696            let mut buffer = language::Buffer::new(0, "abcde", cx);
 6697            // Ensure automatic grouping doesn't occur.
 6698            buffer.set_group_interval(Duration::ZERO);
 6699            buffer
 6700        });
 6701
 6702        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6703        cx.add_window(Default::default(), |cx| {
 6704            let mut editor = build_editor(buffer.clone(), cx);
 6705
 6706            // Start a new IME composition.
 6707            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6708            editor.replace_and_mark_text_in_range(Some(0..1), "á", None, cx);
 6709            editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
 6710            assert_eq!(editor.text(cx), "äbcde");
 6711            assert_eq!(editor.marked_text_range(cx), Some(0..1));
 6712
 6713            // Finalize IME composition.
 6714            editor.replace_text_in_range(Some(0..1), "ā", cx);
 6715            assert_eq!(editor.text(cx), "ābcde");
 6716            assert_eq!(editor.marked_text_range(cx), None);
 6717
 6718            // IME composition edits are grouped and are undone/redone at once.
 6719            editor.undo(&Default::default(), cx);
 6720            assert_eq!(editor.text(cx), "abcde");
 6721            assert_eq!(editor.marked_text_range(cx), None);
 6722            editor.redo(&Default::default(), cx);
 6723            assert_eq!(editor.text(cx), "ābcde");
 6724            assert_eq!(editor.marked_text_range(cx), None);
 6725
 6726            // Start a new IME composition.
 6727            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6728            assert_eq!(editor.marked_text_range(cx), Some(0..1));
 6729
 6730            // Undoing during an IME composition cancels it.
 6731            editor.undo(&Default::default(), cx);
 6732            assert_eq!(editor.text(cx), "ābcde");
 6733            assert_eq!(editor.marked_text_range(cx), None);
 6734
 6735            editor
 6736        });
 6737    }
 6738
 6739    #[gpui::test]
 6740    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6741        cx.set_global(Settings::test(cx));
 6742
 6743        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6744        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6745        editor.update(cx, |view, cx| {
 6746            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6747        });
 6748        assert_eq!(
 6749            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6750            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6751        );
 6752
 6753        editor.update(cx, |view, cx| {
 6754            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6755        });
 6756
 6757        assert_eq!(
 6758            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6759            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6760        );
 6761
 6762        editor.update(cx, |view, cx| {
 6763            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6764        });
 6765
 6766        assert_eq!(
 6767            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6768            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6769        );
 6770
 6771        editor.update(cx, |view, cx| {
 6772            view.end_selection(cx);
 6773            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6774        });
 6775
 6776        assert_eq!(
 6777            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6778            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6779        );
 6780
 6781        editor.update(cx, |view, cx| {
 6782            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6783            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6784        });
 6785
 6786        assert_eq!(
 6787            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6788            [
 6789                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6790                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6791            ]
 6792        );
 6793
 6794        editor.update(cx, |view, cx| {
 6795            view.end_selection(cx);
 6796        });
 6797
 6798        assert_eq!(
 6799            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6800            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6801        );
 6802    }
 6803
 6804    #[gpui::test]
 6805    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6806        cx.set_global(Settings::test(cx));
 6807        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6808        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6809
 6810        view.update(cx, |view, cx| {
 6811            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6812            assert_eq!(
 6813                view.selections.display_ranges(cx),
 6814                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6815            );
 6816        });
 6817
 6818        view.update(cx, |view, cx| {
 6819            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6820            assert_eq!(
 6821                view.selections.display_ranges(cx),
 6822                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6823            );
 6824        });
 6825
 6826        view.update(cx, |view, cx| {
 6827            view.cancel(&Cancel, cx);
 6828            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6829            assert_eq!(
 6830                view.selections.display_ranges(cx),
 6831                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6832            );
 6833        });
 6834    }
 6835
 6836    #[gpui::test]
 6837    fn test_clone(cx: &mut gpui::MutableAppContext) {
 6838        let (text, selection_ranges) = marked_text_ranges(indoc! {"
 6839            one
 6840            two
 6841            three[]
 6842            four
 6843            five[]
 6844        "});
 6845        cx.set_global(Settings::test(cx));
 6846        let buffer = MultiBuffer::build_simple(&text, cx);
 6847
 6848        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6849
 6850        editor.update(cx, |editor, cx| {
 6851            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 6852            editor.fold_ranges(
 6853                [
 6854                    Point::new(1, 0)..Point::new(2, 0),
 6855                    Point::new(3, 0)..Point::new(4, 0),
 6856                ],
 6857                cx,
 6858            );
 6859        });
 6860
 6861        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 6862            cx.add_window(Default::default(), |cx| editor.clone(cx))
 6863        });
 6864
 6865        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 6866        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 6867
 6868        assert_eq!(
 6869            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 6870            editor.update(cx, |e, cx| e.display_text(cx))
 6871        );
 6872        assert_eq!(
 6873            cloned_snapshot
 6874                .folds_in_range(0..text.len())
 6875                .collect::<Vec<_>>(),
 6876            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 6877        );
 6878        assert_set_eq!(
 6879            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 6880            editor.read(cx).selections.ranges(cx)
 6881        );
 6882        assert_set_eq!(
 6883            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 6884            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 6885        );
 6886    }
 6887
 6888    #[gpui::test]
 6889    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6890        cx.set_global(Settings::test(cx));
 6891        use workspace::Item;
 6892        let pane = cx.add_view(Default::default(), |cx| Pane::new(cx));
 6893        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6894
 6895        cx.add_window(Default::default(), |cx| {
 6896            let mut editor = build_editor(buffer.clone(), cx);
 6897            let handle = cx.handle();
 6898            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 6899
 6900            fn pop_history(
 6901                editor: &mut Editor,
 6902                cx: &mut MutableAppContext,
 6903            ) -> Option<NavigationEntry> {
 6904                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 6905            }
 6906
 6907            // Move the cursor a small distance.
 6908            // Nothing is added to the navigation history.
 6909            editor.change_selections(None, cx, |s| {
 6910                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 6911            });
 6912            editor.change_selections(None, cx, |s| {
 6913                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 6914            });
 6915            assert!(pop_history(&mut editor, cx).is_none());
 6916
 6917            // Move the cursor a large distance.
 6918            // The history can jump back to the previous position.
 6919            editor.change_selections(None, cx, |s| {
 6920                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 6921            });
 6922            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6923            editor.navigate(nav_entry.data.unwrap(), cx);
 6924            assert_eq!(nav_entry.item.id(), cx.view_id());
 6925            assert_eq!(
 6926                editor.selections.display_ranges(cx),
 6927                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6928            );
 6929            assert!(pop_history(&mut editor, cx).is_none());
 6930
 6931            // Move the cursor a small distance via the mouse.
 6932            // Nothing is added to the navigation history.
 6933            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6934            editor.end_selection(cx);
 6935            assert_eq!(
 6936                editor.selections.display_ranges(cx),
 6937                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6938            );
 6939            assert!(pop_history(&mut editor, cx).is_none());
 6940
 6941            // Move the cursor a large distance via the mouse.
 6942            // The history can jump back to the previous position.
 6943            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6944            editor.end_selection(cx);
 6945            assert_eq!(
 6946                editor.selections.display_ranges(cx),
 6947                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6948            );
 6949            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6950            editor.navigate(nav_entry.data.unwrap(), cx);
 6951            assert_eq!(nav_entry.item.id(), cx.view_id());
 6952            assert_eq!(
 6953                editor.selections.display_ranges(cx),
 6954                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6955            );
 6956            assert!(pop_history(&mut editor, cx).is_none());
 6957
 6958            // Set scroll position to check later
 6959            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6960            let original_scroll_position = editor.scroll_position;
 6961            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6962
 6963            // Jump to the end of the document and adjust scroll
 6964            editor.move_to_end(&MoveToEnd, cx);
 6965            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6966            assert_ne!(editor.scroll_position, original_scroll_position);
 6967            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6968
 6969            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6970            editor.navigate(nav_entry.data.unwrap(), cx);
 6971            assert_eq!(editor.scroll_position, original_scroll_position);
 6972            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6973
 6974            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6975            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6976            invalid_anchor.text_anchor.buffer_id = Some(999);
 6977            let invalid_point = Point::new(9999, 0);
 6978            editor.navigate(
 6979                Box::new(NavigationData {
 6980                    cursor_anchor: invalid_anchor.clone(),
 6981                    cursor_position: invalid_point,
 6982                    scroll_top_anchor: invalid_anchor.clone(),
 6983                    scroll_top_row: invalid_point.row,
 6984                    scroll_position: Default::default(),
 6985                }),
 6986                cx,
 6987            );
 6988            assert_eq!(
 6989                editor.selections.display_ranges(cx),
 6990                &[editor.max_point(cx)..editor.max_point(cx)]
 6991            );
 6992            assert_eq!(
 6993                editor.scroll_position(cx),
 6994                vec2f(0., editor.max_point(cx).row() as f32)
 6995            );
 6996
 6997            editor
 6998        });
 6999    }
 7000
 7001    #[gpui::test]
 7002    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 7003        cx.set_global(Settings::test(cx));
 7004        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7005        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7006
 7007        view.update(cx, |view, cx| {
 7008            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 7009            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7010            view.end_selection(cx);
 7011
 7012            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 7013            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 7014            view.end_selection(cx);
 7015            assert_eq!(
 7016                view.selections.display_ranges(cx),
 7017                [
 7018                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 7019                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 7020                ]
 7021            );
 7022        });
 7023
 7024        view.update(cx, |view, cx| {
 7025            view.cancel(&Cancel, cx);
 7026            assert_eq!(
 7027                view.selections.display_ranges(cx),
 7028                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 7029            );
 7030        });
 7031
 7032        view.update(cx, |view, cx| {
 7033            view.cancel(&Cancel, cx);
 7034            assert_eq!(
 7035                view.selections.display_ranges(cx),
 7036                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 7037            );
 7038        });
 7039    }
 7040
 7041    #[gpui::test]
 7042    fn test_fold(cx: &mut gpui::MutableAppContext) {
 7043        cx.set_global(Settings::test(cx));
 7044        let buffer = MultiBuffer::build_simple(
 7045            &"
 7046                impl Foo {
 7047                    // Hello!
 7048
 7049                    fn a() {
 7050                        1
 7051                    }
 7052
 7053                    fn b() {
 7054                        2
 7055                    }
 7056
 7057                    fn c() {
 7058                        3
 7059                    }
 7060                }
 7061            "
 7062            .unindent(),
 7063            cx,
 7064        );
 7065        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7066
 7067        view.update(cx, |view, cx| {
 7068            view.change_selections(None, cx, |s| {
 7069                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 7070            });
 7071            view.fold(&Fold, cx);
 7072            assert_eq!(
 7073                view.display_text(cx),
 7074                "
 7075                    impl Foo {
 7076                        // Hello!
 7077
 7078                        fn a() {
 7079                            1
 7080                        }
 7081
 7082                        fn b() {…
 7083                        }
 7084
 7085                        fn c() {…
 7086                        }
 7087                    }
 7088                "
 7089                .unindent(),
 7090            );
 7091
 7092            view.fold(&Fold, cx);
 7093            assert_eq!(
 7094                view.display_text(cx),
 7095                "
 7096                    impl Foo {…
 7097                    }
 7098                "
 7099                .unindent(),
 7100            );
 7101
 7102            view.unfold_lines(&UnfoldLines, cx);
 7103            assert_eq!(
 7104                view.display_text(cx),
 7105                "
 7106                    impl Foo {
 7107                        // Hello!
 7108
 7109                        fn a() {
 7110                            1
 7111                        }
 7112
 7113                        fn b() {…
 7114                        }
 7115
 7116                        fn c() {…
 7117                        }
 7118                    }
 7119                "
 7120                .unindent(),
 7121            );
 7122
 7123            view.unfold_lines(&UnfoldLines, cx);
 7124            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7125        });
 7126    }
 7127
 7128    #[gpui::test]
 7129    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7130        cx.set_global(Settings::test(cx));
 7131        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7132        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7133
 7134        buffer.update(cx, |buffer, cx| {
 7135            buffer.edit(
 7136                vec![
 7137                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7138                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7139                ],
 7140                cx,
 7141            );
 7142        });
 7143
 7144        view.update(cx, |view, cx| {
 7145            assert_eq!(
 7146                view.selections.display_ranges(cx),
 7147                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7148            );
 7149
 7150            view.move_down(&MoveDown, cx);
 7151            assert_eq!(
 7152                view.selections.display_ranges(cx),
 7153                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7154            );
 7155
 7156            view.move_right(&MoveRight, cx);
 7157            assert_eq!(
 7158                view.selections.display_ranges(cx),
 7159                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7160            );
 7161
 7162            view.move_left(&MoveLeft, cx);
 7163            assert_eq!(
 7164                view.selections.display_ranges(cx),
 7165                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7166            );
 7167
 7168            view.move_up(&MoveUp, cx);
 7169            assert_eq!(
 7170                view.selections.display_ranges(cx),
 7171                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7172            );
 7173
 7174            view.move_to_end(&MoveToEnd, cx);
 7175            assert_eq!(
 7176                view.selections.display_ranges(cx),
 7177                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7178            );
 7179
 7180            view.move_to_beginning(&MoveToBeginning, cx);
 7181            assert_eq!(
 7182                view.selections.display_ranges(cx),
 7183                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7184            );
 7185
 7186            view.change_selections(None, cx, |s| {
 7187                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 7188            });
 7189            view.select_to_beginning(&SelectToBeginning, cx);
 7190            assert_eq!(
 7191                view.selections.display_ranges(cx),
 7192                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7193            );
 7194
 7195            view.select_to_end(&SelectToEnd, cx);
 7196            assert_eq!(
 7197                view.selections.display_ranges(cx),
 7198                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7199            );
 7200        });
 7201    }
 7202
 7203    #[gpui::test]
 7204    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7205        cx.set_global(Settings::test(cx));
 7206        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7207        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7208
 7209        assert_eq!('ⓐ'.len_utf8(), 3);
 7210        assert_eq!('α'.len_utf8(), 2);
 7211
 7212        view.update(cx, |view, cx| {
 7213            view.fold_ranges(
 7214                vec![
 7215                    Point::new(0, 6)..Point::new(0, 12),
 7216                    Point::new(1, 2)..Point::new(1, 4),
 7217                    Point::new(2, 4)..Point::new(2, 8),
 7218                ],
 7219                cx,
 7220            );
 7221            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7222
 7223            view.move_right(&MoveRight, cx);
 7224            assert_eq!(
 7225                view.selections.display_ranges(cx),
 7226                &[empty_range(0, "".len())]
 7227            );
 7228            view.move_right(&MoveRight, cx);
 7229            assert_eq!(
 7230                view.selections.display_ranges(cx),
 7231                &[empty_range(0, "ⓐⓑ".len())]
 7232            );
 7233            view.move_right(&MoveRight, cx);
 7234            assert_eq!(
 7235                view.selections.display_ranges(cx),
 7236                &[empty_range(0, "ⓐⓑ…".len())]
 7237            );
 7238
 7239            view.move_down(&MoveDown, cx);
 7240            assert_eq!(
 7241                view.selections.display_ranges(cx),
 7242                &[empty_range(1, "ab…".len())]
 7243            );
 7244            view.move_left(&MoveLeft, cx);
 7245            assert_eq!(
 7246                view.selections.display_ranges(cx),
 7247                &[empty_range(1, "ab".len())]
 7248            );
 7249            view.move_left(&MoveLeft, cx);
 7250            assert_eq!(
 7251                view.selections.display_ranges(cx),
 7252                &[empty_range(1, "a".len())]
 7253            );
 7254
 7255            view.move_down(&MoveDown, cx);
 7256            assert_eq!(
 7257                view.selections.display_ranges(cx),
 7258                &[empty_range(2, "α".len())]
 7259            );
 7260            view.move_right(&MoveRight, cx);
 7261            assert_eq!(
 7262                view.selections.display_ranges(cx),
 7263                &[empty_range(2, "αβ".len())]
 7264            );
 7265            view.move_right(&MoveRight, cx);
 7266            assert_eq!(
 7267                view.selections.display_ranges(cx),
 7268                &[empty_range(2, "αβ…".len())]
 7269            );
 7270            view.move_right(&MoveRight, cx);
 7271            assert_eq!(
 7272                view.selections.display_ranges(cx),
 7273                &[empty_range(2, "αβ…ε".len())]
 7274            );
 7275
 7276            view.move_up(&MoveUp, cx);
 7277            assert_eq!(
 7278                view.selections.display_ranges(cx),
 7279                &[empty_range(1, "ab…e".len())]
 7280            );
 7281            view.move_up(&MoveUp, cx);
 7282            assert_eq!(
 7283                view.selections.display_ranges(cx),
 7284                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7285            );
 7286            view.move_left(&MoveLeft, cx);
 7287            assert_eq!(
 7288                view.selections.display_ranges(cx),
 7289                &[empty_range(0, "ⓐⓑ…".len())]
 7290            );
 7291            view.move_left(&MoveLeft, cx);
 7292            assert_eq!(
 7293                view.selections.display_ranges(cx),
 7294                &[empty_range(0, "ⓐⓑ".len())]
 7295            );
 7296            view.move_left(&MoveLeft, cx);
 7297            assert_eq!(
 7298                view.selections.display_ranges(cx),
 7299                &[empty_range(0, "".len())]
 7300            );
 7301        });
 7302    }
 7303
 7304    #[gpui::test]
 7305    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7306        cx.set_global(Settings::test(cx));
 7307        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7308        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7309        view.update(cx, |view, cx| {
 7310            view.change_selections(None, cx, |s| {
 7311                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7312            });
 7313            view.move_down(&MoveDown, cx);
 7314            assert_eq!(
 7315                view.selections.display_ranges(cx),
 7316                &[empty_range(1, "abcd".len())]
 7317            );
 7318
 7319            view.move_down(&MoveDown, cx);
 7320            assert_eq!(
 7321                view.selections.display_ranges(cx),
 7322                &[empty_range(2, "αβγ".len())]
 7323            );
 7324
 7325            view.move_down(&MoveDown, cx);
 7326            assert_eq!(
 7327                view.selections.display_ranges(cx),
 7328                &[empty_range(3, "abcd".len())]
 7329            );
 7330
 7331            view.move_down(&MoveDown, cx);
 7332            assert_eq!(
 7333                view.selections.display_ranges(cx),
 7334                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7335            );
 7336
 7337            view.move_up(&MoveUp, cx);
 7338            assert_eq!(
 7339                view.selections.display_ranges(cx),
 7340                &[empty_range(3, "abcd".len())]
 7341            );
 7342
 7343            view.move_up(&MoveUp, cx);
 7344            assert_eq!(
 7345                view.selections.display_ranges(cx),
 7346                &[empty_range(2, "αβγ".len())]
 7347            );
 7348        });
 7349    }
 7350
 7351    #[gpui::test]
 7352    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7353        cx.set_global(Settings::test(cx));
 7354        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7355        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7356        view.update(cx, |view, cx| {
 7357            view.change_selections(None, cx, |s| {
 7358                s.select_display_ranges([
 7359                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7360                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7361                ]);
 7362            });
 7363        });
 7364
 7365        view.update(cx, |view, cx| {
 7366            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7367            assert_eq!(
 7368                view.selections.display_ranges(cx),
 7369                &[
 7370                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7371                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7372                ]
 7373            );
 7374        });
 7375
 7376        view.update(cx, |view, cx| {
 7377            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7378            assert_eq!(
 7379                view.selections.display_ranges(cx),
 7380                &[
 7381                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7382                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7383                ]
 7384            );
 7385        });
 7386
 7387        view.update(cx, |view, cx| {
 7388            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7389            assert_eq!(
 7390                view.selections.display_ranges(cx),
 7391                &[
 7392                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7393                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7394                ]
 7395            );
 7396        });
 7397
 7398        view.update(cx, |view, cx| {
 7399            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7400            assert_eq!(
 7401                view.selections.display_ranges(cx),
 7402                &[
 7403                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7404                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7405                ]
 7406            );
 7407        });
 7408
 7409        // Moving to the end of line again is a no-op.
 7410        view.update(cx, |view, cx| {
 7411            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7412            assert_eq!(
 7413                view.selections.display_ranges(cx),
 7414                &[
 7415                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7416                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7417                ]
 7418            );
 7419        });
 7420
 7421        view.update(cx, |view, cx| {
 7422            view.move_left(&MoveLeft, cx);
 7423            view.select_to_beginning_of_line(
 7424                &SelectToBeginningOfLine {
 7425                    stop_at_soft_wraps: true,
 7426                },
 7427                cx,
 7428            );
 7429            assert_eq!(
 7430                view.selections.display_ranges(cx),
 7431                &[
 7432                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7433                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7434                ]
 7435            );
 7436        });
 7437
 7438        view.update(cx, |view, cx| {
 7439            view.select_to_beginning_of_line(
 7440                &SelectToBeginningOfLine {
 7441                    stop_at_soft_wraps: true,
 7442                },
 7443                cx,
 7444            );
 7445            assert_eq!(
 7446                view.selections.display_ranges(cx),
 7447                &[
 7448                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7449                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7450                ]
 7451            );
 7452        });
 7453
 7454        view.update(cx, |view, cx| {
 7455            view.select_to_beginning_of_line(
 7456                &SelectToBeginningOfLine {
 7457                    stop_at_soft_wraps: true,
 7458                },
 7459                cx,
 7460            );
 7461            assert_eq!(
 7462                view.selections.display_ranges(cx),
 7463                &[
 7464                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7465                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7466                ]
 7467            );
 7468        });
 7469
 7470        view.update(cx, |view, cx| {
 7471            view.select_to_end_of_line(
 7472                &SelectToEndOfLine {
 7473                    stop_at_soft_wraps: true,
 7474                },
 7475                cx,
 7476            );
 7477            assert_eq!(
 7478                view.selections.display_ranges(cx),
 7479                &[
 7480                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7481                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7482                ]
 7483            );
 7484        });
 7485
 7486        view.update(cx, |view, cx| {
 7487            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7488            assert_eq!(view.display_text(cx), "ab\n  de");
 7489            assert_eq!(
 7490                view.selections.display_ranges(cx),
 7491                &[
 7492                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7493                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7494                ]
 7495            );
 7496        });
 7497
 7498        view.update(cx, |view, cx| {
 7499            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7500            assert_eq!(view.display_text(cx), "\n");
 7501            assert_eq!(
 7502                view.selections.display_ranges(cx),
 7503                &[
 7504                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7505                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7506                ]
 7507            );
 7508        });
 7509    }
 7510
 7511    #[gpui::test]
 7512    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7513        cx.set_global(Settings::test(cx));
 7514        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7515        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7516        view.update(cx, |view, cx| {
 7517            view.change_selections(None, cx, |s| {
 7518                s.select_display_ranges([
 7519                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7520                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7521                ])
 7522            });
 7523
 7524            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7525            assert_selection_ranges(
 7526                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7527                vec![('<', '>'), ('[', ']')],
 7528                view,
 7529                cx,
 7530            );
 7531
 7532            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7533            assert_selection_ranges(
 7534                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7535                vec![('<', '>'), ('[', ']')],
 7536                view,
 7537                cx,
 7538            );
 7539
 7540            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7541            assert_selection_ranges(
 7542                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7543                vec![('<', '>'), ('[', ']')],
 7544                view,
 7545                cx,
 7546            );
 7547
 7548            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7549            assert_selection_ranges(
 7550                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7551                vec![('<', '>'), ('[', ']')],
 7552                view,
 7553                cx,
 7554            );
 7555
 7556            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7557            assert_selection_ranges(
 7558                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7559                vec![('<', '>'), ('[', ']')],
 7560                view,
 7561                cx,
 7562            );
 7563
 7564            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7565            assert_selection_ranges(
 7566                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7567                vec![('<', '>'), ('[', ']')],
 7568                view,
 7569                cx,
 7570            );
 7571
 7572            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7573            assert_selection_ranges(
 7574                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7575                vec![('<', '>'), ('[', ']')],
 7576                view,
 7577                cx,
 7578            );
 7579
 7580            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7581            assert_selection_ranges(
 7582                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7583                vec![('<', '>'), ('[', ']')],
 7584                view,
 7585                cx,
 7586            );
 7587
 7588            view.move_right(&MoveRight, cx);
 7589            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7590            assert_selection_ranges(
 7591                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7592                vec![('<', '>'), ('[', ']')],
 7593                view,
 7594                cx,
 7595            );
 7596
 7597            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7598            assert_selection_ranges(
 7599                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7600                vec![('<', '>'), ('[', ']')],
 7601                view,
 7602                cx,
 7603            );
 7604
 7605            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7606            assert_selection_ranges(
 7607                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7608                vec![('<', '>'), ('[', ']')],
 7609                view,
 7610                cx,
 7611            );
 7612        });
 7613    }
 7614
 7615    #[gpui::test]
 7616    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7617        cx.set_global(Settings::test(cx));
 7618        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7619        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7620
 7621        view.update(cx, |view, cx| {
 7622            view.set_wrap_width(Some(140.), cx);
 7623            assert_eq!(
 7624                view.display_text(cx),
 7625                "use one::{\n    two::three::\n    four::five\n};"
 7626            );
 7627
 7628            view.change_selections(None, cx, |s| {
 7629                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7630            });
 7631
 7632            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7633            assert_eq!(
 7634                view.selections.display_ranges(cx),
 7635                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7636            );
 7637
 7638            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7639            assert_eq!(
 7640                view.selections.display_ranges(cx),
 7641                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7642            );
 7643
 7644            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7645            assert_eq!(
 7646                view.selections.display_ranges(cx),
 7647                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7648            );
 7649
 7650            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7651            assert_eq!(
 7652                view.selections.display_ranges(cx),
 7653                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7654            );
 7655
 7656            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7657            assert_eq!(
 7658                view.selections.display_ranges(cx),
 7659                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7660            );
 7661
 7662            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7663            assert_eq!(
 7664                view.selections.display_ranges(cx),
 7665                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7666            );
 7667        });
 7668    }
 7669
 7670    #[gpui::test]
 7671    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7672        cx.set_global(Settings::test(cx));
 7673        let (text, ranges) = marked_text_ranges("one [two three] four");
 7674        let buffer = MultiBuffer::build_simple(&text, cx);
 7675
 7676        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7677
 7678        editor.update(cx, |editor, cx| {
 7679            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
 7680            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7681            assert_eq!(editor.text(cx), " four");
 7682        });
 7683    }
 7684
 7685    #[gpui::test]
 7686    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7687        cx.set_global(Settings::test(cx));
 7688        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7689        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7690
 7691        view.update(cx, |view, cx| {
 7692            view.change_selections(None, cx, |s| {
 7693                s.select_display_ranges([
 7694                    // an empty selection - the preceding word fragment is deleted
 7695                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7696                    // characters selected - they are deleted
 7697                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7698                ])
 7699            });
 7700            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7701        });
 7702
 7703        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7704
 7705        view.update(cx, |view, cx| {
 7706            view.change_selections(None, cx, |s| {
 7707                s.select_display_ranges([
 7708                    // an empty selection - the following word fragment is deleted
 7709                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7710                    // characters selected - they are deleted
 7711                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7712                ])
 7713            });
 7714            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7715        });
 7716
 7717        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7718    }
 7719
 7720    #[gpui::test]
 7721    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7722        cx.set_global(Settings::test(cx));
 7723        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7724        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7725
 7726        view.update(cx, |view, cx| {
 7727            view.change_selections(None, cx, |s| {
 7728                s.select_display_ranges([
 7729                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7730                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7731                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7732                ])
 7733            });
 7734
 7735            view.newline(&Newline, cx);
 7736            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7737        });
 7738    }
 7739
 7740    #[gpui::test]
 7741    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7742        cx.set_global(Settings::test(cx));
 7743        let buffer = MultiBuffer::build_simple(
 7744            "
 7745                a
 7746                b(
 7747                    X
 7748                )
 7749                c(
 7750                    X
 7751                )
 7752            "
 7753            .unindent()
 7754            .as_str(),
 7755            cx,
 7756        );
 7757
 7758        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7759            let mut editor = build_editor(buffer.clone(), cx);
 7760            editor.change_selections(None, cx, |s| {
 7761                s.select_ranges([
 7762                    Point::new(2, 4)..Point::new(2, 5),
 7763                    Point::new(5, 4)..Point::new(5, 5),
 7764                ])
 7765            });
 7766            editor
 7767        });
 7768
 7769        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7770        buffer.update(cx, |buffer, cx| {
 7771            buffer.edit(
 7772                [
 7773                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7774                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7775                ],
 7776                cx,
 7777            );
 7778            assert_eq!(
 7779                buffer.read(cx).text(),
 7780                "
 7781                    a
 7782                    b()
 7783                    c()
 7784                "
 7785                .unindent()
 7786            );
 7787        });
 7788
 7789        editor.update(cx, |editor, cx| {
 7790            assert_eq!(
 7791                editor.selections.ranges(cx),
 7792                &[
 7793                    Point::new(1, 2)..Point::new(1, 2),
 7794                    Point::new(2, 2)..Point::new(2, 2),
 7795                ],
 7796            );
 7797
 7798            editor.newline(&Newline, cx);
 7799            assert_eq!(
 7800                editor.text(cx),
 7801                "
 7802                    a
 7803                    b(
 7804                    )
 7805                    c(
 7806                    )
 7807                "
 7808                .unindent()
 7809            );
 7810
 7811            // The selections are moved after the inserted newlines
 7812            assert_eq!(
 7813                editor.selections.ranges(cx),
 7814                &[
 7815                    Point::new(2, 0)..Point::new(2, 0),
 7816                    Point::new(4, 0)..Point::new(4, 0),
 7817                ],
 7818            );
 7819        });
 7820    }
 7821
 7822    #[gpui::test]
 7823    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7824        cx.set_global(Settings::test(cx));
 7825        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7826        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7827            let mut editor = build_editor(buffer.clone(), cx);
 7828            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 7829            editor
 7830        });
 7831
 7832        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7833        buffer.update(cx, |buffer, cx| {
 7834            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7835            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7836        });
 7837
 7838        editor.update(cx, |editor, cx| {
 7839            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 7840
 7841            editor.insert("Z", cx);
 7842            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7843
 7844            // The selections are moved after the inserted characters
 7845            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 7846        });
 7847    }
 7848
 7849    #[gpui::test]
 7850    async fn test_tab(cx: &mut gpui::TestAppContext) {
 7851        let mut cx = EditorTestContext::new(cx).await;
 7852        cx.update(|cx| {
 7853            cx.update_global::<Settings, _, _>(|settings, _| {
 7854                settings.editor_overrides.tab_size = Some(NonZeroU32::new(3).unwrap());
 7855            });
 7856        });
 7857        cx.set_state(indoc! {"
 7858            |ab|c
 7859            |🏀|🏀|efg
 7860            d|
 7861        "});
 7862        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7863        cx.assert_editor_state(indoc! {"
 7864              |ab |c
 7865              |🏀  |🏀  |efg
 7866           d  |
 7867        "});
 7868    }
 7869
 7870    #[gpui::test]
 7871    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 7872        let mut cx = EditorTestContext::new(cx).await;
 7873
 7874        cx.set_state(indoc! {"
 7875              [one} [two}
 7876            three
 7877             four"});
 7878        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7879        cx.assert_editor_state(indoc! {"
 7880                [one} [two}
 7881            three
 7882             four"});
 7883
 7884        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7885        cx.assert_editor_state(indoc! {"
 7886            [one} [two}
 7887            three
 7888             four"});
 7889
 7890        // select across line ending
 7891        cx.set_state(indoc! {"
 7892            one two
 7893            t[hree
 7894            } four"});
 7895        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7896        cx.assert_editor_state(indoc! {"
 7897            one two
 7898                t[hree
 7899            } four"});
 7900
 7901        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7902        cx.assert_editor_state(indoc! {"
 7903            one two
 7904            t[hree
 7905            } four"});
 7906
 7907        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7908        cx.set_state(indoc! {"
 7909            one two
 7910            |three
 7911                four"});
 7912        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7913        cx.assert_editor_state(indoc! {"
 7914            one two
 7915                |three
 7916                four"});
 7917
 7918        cx.set_state(indoc! {"
 7919            one two
 7920            |    three
 7921             four"});
 7922        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7923        cx.assert_editor_state(indoc! {"
 7924            one two
 7925            |three
 7926             four"});
 7927    }
 7928
 7929    #[gpui::test]
 7930    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 7931        let mut cx = EditorTestContext::new(cx).await;
 7932        cx.update(|cx| {
 7933            cx.update_global::<Settings, _, _>(|settings, _| {
 7934                settings.editor_overrides.hard_tabs = Some(true);
 7935            });
 7936        });
 7937
 7938        // select two ranges on one line
 7939        cx.set_state(indoc! {"
 7940            [one} [two}
 7941            three
 7942            four"});
 7943        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7944        cx.assert_editor_state(indoc! {"
 7945            \t[one} [two}
 7946            three
 7947            four"});
 7948        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7949        cx.assert_editor_state(indoc! {"
 7950            \t\t[one} [two}
 7951            three
 7952            four"});
 7953        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7954        cx.assert_editor_state(indoc! {"
 7955            \t[one} [two}
 7956            three
 7957            four"});
 7958        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7959        cx.assert_editor_state(indoc! {"
 7960            [one} [two}
 7961            three
 7962            four"});
 7963
 7964        // select across a line ending
 7965        cx.set_state(indoc! {"
 7966            one two
 7967            t[hree
 7968            }four"});
 7969        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7970        cx.assert_editor_state(indoc! {"
 7971            one two
 7972            \tt[hree
 7973            }four"});
 7974        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7975        cx.assert_editor_state(indoc! {"
 7976            one two
 7977            \t\tt[hree
 7978            }four"});
 7979        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7980        cx.assert_editor_state(indoc! {"
 7981            one two
 7982            \tt[hree
 7983            }four"});
 7984        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7985        cx.assert_editor_state(indoc! {"
 7986            one two
 7987            t[hree
 7988            }four"});
 7989
 7990        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7991        cx.set_state(indoc! {"
 7992            one two
 7993            |three
 7994            four"});
 7995        cx.assert_editor_state(indoc! {"
 7996            one two
 7997            |three
 7998            four"});
 7999        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8000        cx.assert_editor_state(indoc! {"
 8001            one two
 8002            \t|three
 8003            four"});
 8004        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8005        cx.assert_editor_state(indoc! {"
 8006            one two
 8007            |three
 8008            four"});
 8009    }
 8010
 8011    #[gpui::test]
 8012    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 8013        cx.set_global(
 8014            Settings::test(cx)
 8015                .with_language_defaults(
 8016                    "TOML",
 8017                    EditorSettings {
 8018                        tab_size: Some(2.try_into().unwrap()),
 8019                        ..Default::default()
 8020                    },
 8021                )
 8022                .with_language_defaults(
 8023                    "Rust",
 8024                    EditorSettings {
 8025                        tab_size: Some(4.try_into().unwrap()),
 8026                        ..Default::default()
 8027                    },
 8028                ),
 8029        );
 8030        let toml_language = Arc::new(Language::new(
 8031            LanguageConfig {
 8032                name: "TOML".into(),
 8033                ..Default::default()
 8034            },
 8035            None,
 8036        ));
 8037        let rust_language = Arc::new(Language::new(
 8038            LanguageConfig {
 8039                name: "Rust".into(),
 8040                ..Default::default()
 8041            },
 8042            None,
 8043        ));
 8044
 8045        let toml_buffer = cx
 8046            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 8047        let rust_buffer = cx.add_model(|cx| {
 8048            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 8049        });
 8050        let multibuffer = cx.add_model(|cx| {
 8051            let mut multibuffer = MultiBuffer::new(0);
 8052            multibuffer.push_excerpts(
 8053                toml_buffer.clone(),
 8054                [ExcerptRange {
 8055                    context: Point::new(0, 0)..Point::new(2, 0),
 8056                    primary: None,
 8057                }],
 8058                cx,
 8059            );
 8060            multibuffer.push_excerpts(
 8061                rust_buffer.clone(),
 8062                [ExcerptRange {
 8063                    context: Point::new(0, 0)..Point::new(1, 0),
 8064                    primary: None,
 8065                }],
 8066                cx,
 8067            );
 8068            multibuffer
 8069        });
 8070
 8071        cx.add_window(Default::default(), |cx| {
 8072            let mut editor = build_editor(multibuffer, cx);
 8073
 8074            assert_eq!(
 8075                editor.text(cx),
 8076                indoc! {"
 8077                    a = 1
 8078                    b = 2
 8079
 8080                    const c: usize = 3;
 8081                "}
 8082            );
 8083
 8084            select_ranges(
 8085                &mut editor,
 8086                indoc! {"
 8087                    [a] = 1
 8088                    b = 2
 8089
 8090                    [const c:] usize = 3;
 8091                "},
 8092                cx,
 8093            );
 8094
 8095            editor.tab(&Tab, cx);
 8096            assert_text_with_selections(
 8097                &mut editor,
 8098                indoc! {"
 8099                      [a] = 1
 8100                    b = 2
 8101
 8102                        [const c:] usize = 3;
 8103                "},
 8104                cx,
 8105            );
 8106            editor.tab_prev(&TabPrev, cx);
 8107            assert_text_with_selections(
 8108                &mut editor,
 8109                indoc! {"
 8110                    [a] = 1
 8111                    b = 2
 8112
 8113                    [const c:] usize = 3;
 8114                "},
 8115                cx,
 8116            );
 8117
 8118            editor
 8119        });
 8120    }
 8121
 8122    #[gpui::test]
 8123    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 8124        let mut cx = EditorTestContext::new(cx).await;
 8125        // Basic backspace
 8126        cx.set_state(indoc! {"
 8127            on|e two three
 8128            fou[r} five six
 8129            seven {eight nine
 8130            ]ten"});
 8131        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8132        cx.assert_editor_state(indoc! {"
 8133            o|e two three
 8134            fou| five six
 8135            seven |ten"});
 8136
 8137        // Test backspace inside and around indents
 8138        cx.set_state(indoc! {"
 8139            zero
 8140                |one
 8141                    |two
 8142                | | |  three
 8143            |  |  four"});
 8144        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8145        cx.assert_editor_state(indoc! {"
 8146            zero
 8147            |one
 8148                |two
 8149            |  three|  four"});
 8150
 8151        // Test backspace with line_mode set to true
 8152        cx.update_editor(|e, _| e.selections.line_mode = true);
 8153        cx.set_state(indoc! {"
 8154            The |quick |brown
 8155            fox jumps over
 8156            the lazy dog
 8157            |The qu[ick b}rown"});
 8158        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8159        cx.assert_editor_state(indoc! {"
 8160            |fox jumps over
 8161            the lazy dog|"});
 8162    }
 8163
 8164    #[gpui::test]
 8165    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8166        let mut cx = EditorTestContext::new(cx).await;
 8167
 8168        cx.set_state(indoc! {"
 8169            on|e two three
 8170            fou[r} five six
 8171            seven {eight nine
 8172            ]ten"});
 8173        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8174        cx.assert_editor_state(indoc! {"
 8175            on| two three
 8176            fou| five six
 8177            seven |ten"});
 8178
 8179        // Test backspace with line_mode set to true
 8180        cx.update_editor(|e, _| e.selections.line_mode = true);
 8181        cx.set_state(indoc! {"
 8182            The |quick |brown
 8183            fox {jum]ps over
 8184            the lazy dog
 8185            |The qu[ick b}rown"});
 8186        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8187        cx.assert_editor_state("|the lazy dog|");
 8188    }
 8189
 8190    #[gpui::test]
 8191    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8192        cx.set_global(Settings::test(cx));
 8193        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8194        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8195        view.update(cx, |view, cx| {
 8196            view.change_selections(None, cx, |s| {
 8197                s.select_display_ranges([
 8198                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8199                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8200                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8201                ])
 8202            });
 8203            view.delete_line(&DeleteLine, cx);
 8204            assert_eq!(view.display_text(cx), "ghi");
 8205            assert_eq!(
 8206                view.selections.display_ranges(cx),
 8207                vec![
 8208                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8209                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8210                ]
 8211            );
 8212        });
 8213
 8214        cx.set_global(Settings::test(cx));
 8215        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8216        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8217        view.update(cx, |view, cx| {
 8218            view.change_selections(None, cx, |s| {
 8219                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8220            });
 8221            view.delete_line(&DeleteLine, cx);
 8222            assert_eq!(view.display_text(cx), "ghi\n");
 8223            assert_eq!(
 8224                view.selections.display_ranges(cx),
 8225                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8226            );
 8227        });
 8228    }
 8229
 8230    #[gpui::test]
 8231    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8232        cx.set_global(Settings::test(cx));
 8233        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8234        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8235        view.update(cx, |view, cx| {
 8236            view.change_selections(None, cx, |s| {
 8237                s.select_display_ranges([
 8238                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8239                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8240                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8241                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8242                ])
 8243            });
 8244            view.duplicate_line(&DuplicateLine, cx);
 8245            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8246            assert_eq!(
 8247                view.selections.display_ranges(cx),
 8248                vec![
 8249                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8250                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8251                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8252                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8253                ]
 8254            );
 8255        });
 8256
 8257        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8258        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8259        view.update(cx, |view, cx| {
 8260            view.change_selections(None, cx, |s| {
 8261                s.select_display_ranges([
 8262                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8263                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8264                ])
 8265            });
 8266            view.duplicate_line(&DuplicateLine, cx);
 8267            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8268            assert_eq!(
 8269                view.selections.display_ranges(cx),
 8270                vec![
 8271                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8272                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8273                ]
 8274            );
 8275        });
 8276    }
 8277
 8278    #[gpui::test]
 8279    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8280        cx.set_global(Settings::test(cx));
 8281        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8282        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8283        view.update(cx, |view, cx| {
 8284            view.fold_ranges(
 8285                vec![
 8286                    Point::new(0, 2)..Point::new(1, 2),
 8287                    Point::new(2, 3)..Point::new(4, 1),
 8288                    Point::new(7, 0)..Point::new(8, 4),
 8289                ],
 8290                cx,
 8291            );
 8292            view.change_selections(None, cx, |s| {
 8293                s.select_display_ranges([
 8294                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8295                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8296                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8297                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8298                ])
 8299            });
 8300            assert_eq!(
 8301                view.display_text(cx),
 8302                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8303            );
 8304
 8305            view.move_line_up(&MoveLineUp, cx);
 8306            assert_eq!(
 8307                view.display_text(cx),
 8308                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8309            );
 8310            assert_eq!(
 8311                view.selections.display_ranges(cx),
 8312                vec![
 8313                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8314                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8315                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8316                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8317                ]
 8318            );
 8319        });
 8320
 8321        view.update(cx, |view, cx| {
 8322            view.move_line_down(&MoveLineDown, cx);
 8323            assert_eq!(
 8324                view.display_text(cx),
 8325                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8326            );
 8327            assert_eq!(
 8328                view.selections.display_ranges(cx),
 8329                vec![
 8330                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8331                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8332                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8333                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8334                ]
 8335            );
 8336        });
 8337
 8338        view.update(cx, |view, cx| {
 8339            view.move_line_down(&MoveLineDown, cx);
 8340            assert_eq!(
 8341                view.display_text(cx),
 8342                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8343            );
 8344            assert_eq!(
 8345                view.selections.display_ranges(cx),
 8346                vec![
 8347                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8348                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8349                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8350                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8351                ]
 8352            );
 8353        });
 8354
 8355        view.update(cx, |view, cx| {
 8356            view.move_line_up(&MoveLineUp, cx);
 8357            assert_eq!(
 8358                view.display_text(cx),
 8359                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8360            );
 8361            assert_eq!(
 8362                view.selections.display_ranges(cx),
 8363                vec![
 8364                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8365                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8366                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8367                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8368                ]
 8369            );
 8370        });
 8371    }
 8372
 8373    #[gpui::test]
 8374    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8375        cx.set_global(Settings::test(cx));
 8376        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8377        let snapshot = buffer.read(cx).snapshot(cx);
 8378        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8379        editor.update(cx, |editor, cx| {
 8380            editor.insert_blocks(
 8381                [BlockProperties {
 8382                    style: BlockStyle::Fixed,
 8383                    position: snapshot.anchor_after(Point::new(2, 0)),
 8384                    disposition: BlockDisposition::Below,
 8385                    height: 1,
 8386                    render: Arc::new(|_| Empty::new().boxed()),
 8387                }],
 8388                cx,
 8389            );
 8390            editor.change_selections(None, cx, |s| {
 8391                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8392            });
 8393            editor.move_line_down(&MoveLineDown, cx);
 8394        });
 8395    }
 8396
 8397    #[gpui::test]
 8398    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8399        cx.set_global(Settings::test(cx));
 8400
 8401        cx.add_window(Default::default(), |cx| {
 8402            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8403
 8404            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8405            editor.transpose(&Default::default(), cx);
 8406            assert_eq!(editor.text(cx), "bac");
 8407            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8408
 8409            editor.transpose(&Default::default(), cx);
 8410            assert_eq!(editor.text(cx), "bca");
 8411            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8412
 8413            editor.transpose(&Default::default(), cx);
 8414            assert_eq!(editor.text(cx), "bac");
 8415            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8416
 8417            editor
 8418        })
 8419        .1;
 8420
 8421        cx.add_window(Default::default(), |cx| {
 8422            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8423
 8424            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8425            editor.transpose(&Default::default(), cx);
 8426            assert_eq!(editor.text(cx), "acb\nde");
 8427            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8428
 8429            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8430            editor.transpose(&Default::default(), cx);
 8431            assert_eq!(editor.text(cx), "acbd\ne");
 8432            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8433
 8434            editor.transpose(&Default::default(), cx);
 8435            assert_eq!(editor.text(cx), "acbde\n");
 8436            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8437
 8438            editor.transpose(&Default::default(), cx);
 8439            assert_eq!(editor.text(cx), "acbd\ne");
 8440            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8441
 8442            editor
 8443        })
 8444        .1;
 8445
 8446        cx.add_window(Default::default(), |cx| {
 8447            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8448
 8449            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8450            editor.transpose(&Default::default(), cx);
 8451            assert_eq!(editor.text(cx), "bacd\ne");
 8452            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8453
 8454            editor.transpose(&Default::default(), cx);
 8455            assert_eq!(editor.text(cx), "bcade\n");
 8456            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8457
 8458            editor.transpose(&Default::default(), cx);
 8459            assert_eq!(editor.text(cx), "bcda\ne");
 8460            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8461
 8462            editor.transpose(&Default::default(), cx);
 8463            assert_eq!(editor.text(cx), "bcade\n");
 8464            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8465
 8466            editor.transpose(&Default::default(), cx);
 8467            assert_eq!(editor.text(cx), "bcaed\n");
 8468            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8469
 8470            editor
 8471        })
 8472        .1;
 8473
 8474        cx.add_window(Default::default(), |cx| {
 8475            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8476
 8477            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8478            editor.transpose(&Default::default(), cx);
 8479            assert_eq!(editor.text(cx), "🏀🍐✋");
 8480            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8481
 8482            editor.transpose(&Default::default(), cx);
 8483            assert_eq!(editor.text(cx), "🏀✋🍐");
 8484            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8485
 8486            editor.transpose(&Default::default(), cx);
 8487            assert_eq!(editor.text(cx), "🏀🍐✋");
 8488            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8489
 8490            editor
 8491        })
 8492        .1;
 8493    }
 8494
 8495    #[gpui::test]
 8496    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8497        let mut cx = EditorTestContext::new(cx).await;
 8498
 8499        cx.set_state("[one✅ }two [three }four [five }six ");
 8500        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8501        cx.assert_editor_state("|two |four |six ");
 8502
 8503        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8504        cx.set_state("two |four |six |");
 8505        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8506        cx.assert_editor_state("two one✅ |four three |six five |");
 8507
 8508        // Paste again but with only two cursors. Since the number of cursors doesn't
 8509        // match the number of slices in the clipboard, the entire clipboard text
 8510        // is pasted at each cursor.
 8511        cx.set_state("|two one✅ four three six five |");
 8512        cx.update_editor(|e, cx| {
 8513            e.handle_input("( ", cx);
 8514            e.paste(&Paste, cx);
 8515            e.handle_input(") ", cx);
 8516        });
 8517        cx.assert_editor_state(indoc! {"
 8518            ( one✅ 
 8519            three 
 8520            five ) |two one✅ four three six five ( one✅ 
 8521            three 
 8522            five ) |"});
 8523
 8524        // Cut with three selections, one of which is full-line.
 8525        cx.set_state(indoc! {"
 8526            1[2}3
 8527            4|567
 8528            [8}9"});
 8529        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8530        cx.assert_editor_state(indoc! {"
 8531            1|3
 8532            |9"});
 8533
 8534        // Paste with three selections, noticing how the copied selection that was full-line
 8535        // gets inserted before the second cursor.
 8536        cx.set_state(indoc! {"
 8537            1|3
 8538            9|
 8539            [o}ne"});
 8540        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8541        cx.assert_editor_state(indoc! {"
 8542            12|3
 8543            4567
 8544            9|
 8545            8|ne"});
 8546
 8547        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8548        cx.set_state(indoc! {"
 8549            The quick brown
 8550            fox ju|mps over
 8551            the lazy dog"});
 8552        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8553        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8554
 8555        // Paste with three selections, noticing how the copied full-line selection is inserted
 8556        // before the empty selections but replaces the selection that is non-empty.
 8557        cx.set_state(indoc! {"
 8558            T|he quick brown
 8559            [fo}x jumps over
 8560            t|he lazy dog"});
 8561        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8562        cx.assert_editor_state(indoc! {"
 8563            fox jumps over
 8564            T|he quick brown
 8565            fox jumps over
 8566            |x jumps over
 8567            fox jumps over
 8568            t|he lazy dog"});
 8569    }
 8570
 8571    #[gpui::test]
 8572    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8573        cx.set_global(Settings::test(cx));
 8574        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8575        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8576        view.update(cx, |view, cx| {
 8577            view.select_all(&SelectAll, cx);
 8578            assert_eq!(
 8579                view.selections.display_ranges(cx),
 8580                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8581            );
 8582        });
 8583    }
 8584
 8585    #[gpui::test]
 8586    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8587        cx.set_global(Settings::test(cx));
 8588        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8589        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8590        view.update(cx, |view, cx| {
 8591            view.change_selections(None, cx, |s| {
 8592                s.select_display_ranges([
 8593                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8594                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8595                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8596                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8597                ])
 8598            });
 8599            view.select_line(&SelectLine, cx);
 8600            assert_eq!(
 8601                view.selections.display_ranges(cx),
 8602                vec![
 8603                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8604                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8605                ]
 8606            );
 8607        });
 8608
 8609        view.update(cx, |view, cx| {
 8610            view.select_line(&SelectLine, cx);
 8611            assert_eq!(
 8612                view.selections.display_ranges(cx),
 8613                vec![
 8614                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8615                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8616                ]
 8617            );
 8618        });
 8619
 8620        view.update(cx, |view, cx| {
 8621            view.select_line(&SelectLine, cx);
 8622            assert_eq!(
 8623                view.selections.display_ranges(cx),
 8624                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8625            );
 8626        });
 8627    }
 8628
 8629    #[gpui::test]
 8630    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8631        cx.set_global(Settings::test(cx));
 8632        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8633        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8634        view.update(cx, |view, cx| {
 8635            view.fold_ranges(
 8636                vec![
 8637                    Point::new(0, 2)..Point::new(1, 2),
 8638                    Point::new(2, 3)..Point::new(4, 1),
 8639                    Point::new(7, 0)..Point::new(8, 4),
 8640                ],
 8641                cx,
 8642            );
 8643            view.change_selections(None, cx, |s| {
 8644                s.select_display_ranges([
 8645                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8646                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8647                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8648                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8649                ])
 8650            });
 8651            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8652        });
 8653
 8654        view.update(cx, |view, cx| {
 8655            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8656            assert_eq!(
 8657                view.display_text(cx),
 8658                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8659            );
 8660            assert_eq!(
 8661                view.selections.display_ranges(cx),
 8662                [
 8663                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8664                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8665                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8666                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8667                ]
 8668            );
 8669        });
 8670
 8671        view.update(cx, |view, cx| {
 8672            view.change_selections(None, cx, |s| {
 8673                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 8674            });
 8675            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8676            assert_eq!(
 8677                view.display_text(cx),
 8678                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8679            );
 8680            assert_eq!(
 8681                view.selections.display_ranges(cx),
 8682                [
 8683                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8684                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8685                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8686                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8687                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8688                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8689                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8690                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8691                ]
 8692            );
 8693        });
 8694    }
 8695
 8696    #[gpui::test]
 8697    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8698        cx.set_global(Settings::test(cx));
 8699        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8700        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8701
 8702        view.update(cx, |view, cx| {
 8703            view.change_selections(None, cx, |s| {
 8704                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 8705            });
 8706        });
 8707        view.update(cx, |view, cx| {
 8708            view.add_selection_above(&AddSelectionAbove, cx);
 8709            assert_eq!(
 8710                view.selections.display_ranges(cx),
 8711                vec![
 8712                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8713                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8714                ]
 8715            );
 8716        });
 8717
 8718        view.update(cx, |view, cx| {
 8719            view.add_selection_above(&AddSelectionAbove, cx);
 8720            assert_eq!(
 8721                view.selections.display_ranges(cx),
 8722                vec![
 8723                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8724                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8725                ]
 8726            );
 8727        });
 8728
 8729        view.update(cx, |view, cx| {
 8730            view.add_selection_below(&AddSelectionBelow, cx);
 8731            assert_eq!(
 8732                view.selections.display_ranges(cx),
 8733                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8734            );
 8735
 8736            view.undo_selection(&UndoSelection, cx);
 8737            assert_eq!(
 8738                view.selections.display_ranges(cx),
 8739                vec![
 8740                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8741                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8742                ]
 8743            );
 8744
 8745            view.redo_selection(&RedoSelection, cx);
 8746            assert_eq!(
 8747                view.selections.display_ranges(cx),
 8748                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8749            );
 8750        });
 8751
 8752        view.update(cx, |view, cx| {
 8753            view.add_selection_below(&AddSelectionBelow, cx);
 8754            assert_eq!(
 8755                view.selections.display_ranges(cx),
 8756                vec![
 8757                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8758                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8759                ]
 8760            );
 8761        });
 8762
 8763        view.update(cx, |view, cx| {
 8764            view.add_selection_below(&AddSelectionBelow, cx);
 8765            assert_eq!(
 8766                view.selections.display_ranges(cx),
 8767                vec![
 8768                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8769                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8770                ]
 8771            );
 8772        });
 8773
 8774        view.update(cx, |view, cx| {
 8775            view.change_selections(None, cx, |s| {
 8776                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 8777            });
 8778        });
 8779        view.update(cx, |view, cx| {
 8780            view.add_selection_below(&AddSelectionBelow, cx);
 8781            assert_eq!(
 8782                view.selections.display_ranges(cx),
 8783                vec![
 8784                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8785                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 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![
 8795                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8796                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8797                ]
 8798            );
 8799        });
 8800
 8801        view.update(cx, |view, cx| {
 8802            view.add_selection_above(&AddSelectionAbove, cx);
 8803            assert_eq!(
 8804                view.selections.display_ranges(cx),
 8805                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8806            );
 8807        });
 8808
 8809        view.update(cx, |view, cx| {
 8810            view.add_selection_above(&AddSelectionAbove, cx);
 8811            assert_eq!(
 8812                view.selections.display_ranges(cx),
 8813                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8814            );
 8815        });
 8816
 8817        view.update(cx, |view, cx| {
 8818            view.change_selections(None, cx, |s| {
 8819                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 8820            });
 8821            view.add_selection_below(&AddSelectionBelow, cx);
 8822            assert_eq!(
 8823                view.selections.display_ranges(cx),
 8824                vec![
 8825                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8826                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8827                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8828                ]
 8829            );
 8830        });
 8831
 8832        view.update(cx, |view, cx| {
 8833            view.add_selection_below(&AddSelectionBelow, cx);
 8834            assert_eq!(
 8835                view.selections.display_ranges(cx),
 8836                vec![
 8837                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8838                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8839                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8840                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8841                ]
 8842            );
 8843        });
 8844
 8845        view.update(cx, |view, cx| {
 8846            view.add_selection_above(&AddSelectionAbove, cx);
 8847            assert_eq!(
 8848                view.selections.display_ranges(cx),
 8849                vec![
 8850                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8851                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8852                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8853                ]
 8854            );
 8855        });
 8856
 8857        view.update(cx, |view, cx| {
 8858            view.change_selections(None, cx, |s| {
 8859                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 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![
 8867                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8868                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8869                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8870                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8871                ]
 8872            );
 8873        });
 8874
 8875        view.update(cx, |view, cx| {
 8876            view.add_selection_below(&AddSelectionBelow, cx);
 8877            assert_eq!(
 8878                view.selections.display_ranges(cx),
 8879                vec![
 8880                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8881                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8882                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8883                ]
 8884            );
 8885        });
 8886    }
 8887
 8888    #[gpui::test]
 8889    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8890        cx.set_global(Settings::test(cx));
 8891
 8892        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8893        let buffer = MultiBuffer::build_simple(&text, cx);
 8894        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8895
 8896        view.update(cx, |view, cx| {
 8897            view.change_selections(None, cx, |s| {
 8898                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 8899            });
 8900            view.select_next(
 8901                &SelectNext {
 8902                    replace_newest: false,
 8903                },
 8904                cx,
 8905            );
 8906            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8907
 8908            view.select_next(
 8909                &SelectNext {
 8910                    replace_newest: false,
 8911                },
 8912                cx,
 8913            );
 8914            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8915
 8916            view.undo_selection(&UndoSelection, cx);
 8917            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8918
 8919            view.redo_selection(&RedoSelection, cx);
 8920            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8921
 8922            view.select_next(
 8923                &SelectNext {
 8924                    replace_newest: false,
 8925                },
 8926                cx,
 8927            );
 8928            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 8929
 8930            view.select_next(
 8931                &SelectNext {
 8932                    replace_newest: false,
 8933                },
 8934                cx,
 8935            );
 8936            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 8937        });
 8938    }
 8939
 8940    #[gpui::test]
 8941    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8942        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8943        let language = Arc::new(Language::new(
 8944            LanguageConfig::default(),
 8945            Some(tree_sitter_rust::language()),
 8946        ));
 8947
 8948        let text = r#"
 8949            use mod1::mod2::{mod3, mod4};
 8950
 8951            fn fn_1(param1: bool, param2: &str) {
 8952                let var1 = "text";
 8953            }
 8954        "#
 8955        .unindent();
 8956
 8957        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8958        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8959        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8960        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8961            .await;
 8962
 8963        view.update(cx, |view, cx| {
 8964            view.change_selections(None, cx, |s| {
 8965                s.select_display_ranges([
 8966                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8967                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8968                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8969                ]);
 8970            });
 8971            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8972        });
 8973        assert_eq!(
 8974            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 8975            &[
 8976                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8977                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8978                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8979            ]
 8980        );
 8981
 8982        view.update(cx, |view, cx| {
 8983            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8984        });
 8985        assert_eq!(
 8986            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8987            &[
 8988                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8989                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8990            ]
 8991        );
 8992
 8993        view.update(cx, |view, cx| {
 8994            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8995        });
 8996        assert_eq!(
 8997            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8998            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8999        );
 9000
 9001        // Trying to expand the selected syntax node one more time has no effect.
 9002        view.update(cx, |view, cx| {
 9003            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9004        });
 9005        assert_eq!(
 9006            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9007            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9008        );
 9009
 9010        view.update(cx, |view, cx| {
 9011            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9012        });
 9013        assert_eq!(
 9014            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9015            &[
 9016                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9017                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9018            ]
 9019        );
 9020
 9021        view.update(cx, |view, cx| {
 9022            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9023        });
 9024        assert_eq!(
 9025            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9026            &[
 9027                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9028                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9029                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9030            ]
 9031        );
 9032
 9033        view.update(cx, |view, cx| {
 9034            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9035        });
 9036        assert_eq!(
 9037            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9038            &[
 9039                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9040                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9041                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9042            ]
 9043        );
 9044
 9045        // Trying to shrink the selected syntax node one more time has no effect.
 9046        view.update(cx, |view, cx| {
 9047            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9048        });
 9049        assert_eq!(
 9050            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9051            &[
 9052                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9053                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9054                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9055            ]
 9056        );
 9057
 9058        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9059        // a fold.
 9060        view.update(cx, |view, cx| {
 9061            view.fold_ranges(
 9062                vec![
 9063                    Point::new(0, 21)..Point::new(0, 24),
 9064                    Point::new(3, 20)..Point::new(3, 22),
 9065                ],
 9066                cx,
 9067            );
 9068            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9069        });
 9070        assert_eq!(
 9071            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9072            &[
 9073                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9074                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9075                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9076            ]
 9077        );
 9078    }
 9079
 9080    #[gpui::test]
 9081    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9082        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9083        let language = Arc::new(
 9084            Language::new(
 9085                LanguageConfig {
 9086                    brackets: vec![
 9087                        BracketPair {
 9088                            start: "{".to_string(),
 9089                            end: "}".to_string(),
 9090                            close: false,
 9091                            newline: true,
 9092                        },
 9093                        BracketPair {
 9094                            start: "(".to_string(),
 9095                            end: ")".to_string(),
 9096                            close: false,
 9097                            newline: true,
 9098                        },
 9099                    ],
 9100                    ..Default::default()
 9101                },
 9102                Some(tree_sitter_rust::language()),
 9103            )
 9104            .with_indents_query(
 9105                r#"
 9106                (_ "(" ")" @end) @indent
 9107                (_ "{" "}" @end) @indent
 9108                "#,
 9109            )
 9110            .unwrap(),
 9111        );
 9112
 9113        let text = "fn a() {}";
 9114
 9115        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9116        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9117        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9118        editor
 9119            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9120            .await;
 9121
 9122        editor.update(cx, |editor, cx| {
 9123            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 9124            editor.newline(&Newline, cx);
 9125            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9126            assert_eq!(
 9127                editor.selections.ranges(cx),
 9128                &[
 9129                    Point::new(1, 4)..Point::new(1, 4),
 9130                    Point::new(3, 4)..Point::new(3, 4),
 9131                    Point::new(5, 0)..Point::new(5, 0)
 9132                ]
 9133            );
 9134        });
 9135    }
 9136
 9137    #[gpui::test]
 9138    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9139        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9140        let language = Arc::new(Language::new(
 9141            LanguageConfig {
 9142                brackets: vec![
 9143                    BracketPair {
 9144                        start: "{".to_string(),
 9145                        end: "}".to_string(),
 9146                        close: true,
 9147                        newline: true,
 9148                    },
 9149                    BracketPair {
 9150                        start: "/*".to_string(),
 9151                        end: " */".to_string(),
 9152                        close: true,
 9153                        newline: true,
 9154                    },
 9155                    BracketPair {
 9156                        start: "[".to_string(),
 9157                        end: "]".to_string(),
 9158                        close: false,
 9159                        newline: true,
 9160                    },
 9161                ],
 9162                autoclose_before: "})]".to_string(),
 9163                ..Default::default()
 9164            },
 9165            Some(tree_sitter_rust::language()),
 9166        ));
 9167
 9168        let text = r#"
 9169            a
 9170
 9171            /
 9172
 9173        "#
 9174        .unindent();
 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 (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9179        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9180            .await;
 9181
 9182        view.update(cx, |view, cx| {
 9183            view.change_selections(None, cx, |s| {
 9184                s.select_display_ranges([
 9185                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9186                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9187                ])
 9188            });
 9189
 9190            view.handle_input("{", cx);
 9191            view.handle_input("{", cx);
 9192            view.handle_input("{", cx);
 9193            assert_eq!(
 9194                view.text(cx),
 9195                "
 9196                {{{}}}
 9197                {{{}}}
 9198                /
 9199
 9200                "
 9201                .unindent()
 9202            );
 9203
 9204            view.move_right(&MoveRight, cx);
 9205            view.handle_input("}", cx);
 9206            view.handle_input("}", cx);
 9207            view.handle_input("}", cx);
 9208            assert_eq!(
 9209                view.text(cx),
 9210                "
 9211                {{{}}}}
 9212                {{{}}}}
 9213                /
 9214
 9215                "
 9216                .unindent()
 9217            );
 9218
 9219            view.undo(&Undo, cx);
 9220            view.handle_input("/", cx);
 9221            view.handle_input("*", cx);
 9222            assert_eq!(
 9223                view.text(cx),
 9224                "
 9225                /* */
 9226                /* */
 9227                /
 9228
 9229                "
 9230                .unindent()
 9231            );
 9232
 9233            view.undo(&Undo, cx);
 9234            view.change_selections(None, cx, |s| {
 9235                s.select_display_ranges([
 9236                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9237                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9238                ])
 9239            });
 9240            view.handle_input("*", cx);
 9241            assert_eq!(
 9242                view.text(cx),
 9243                "
 9244                a
 9245
 9246                /*
 9247                *
 9248                "
 9249                .unindent()
 9250            );
 9251
 9252            // Don't autoclose if the next character isn't whitespace and isn't
 9253            // listed in the language's "autoclose_before" section.
 9254            view.finalize_last_transaction(cx);
 9255            view.change_selections(None, cx, |s| {
 9256                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 9257            });
 9258            view.handle_input("{", cx);
 9259            assert_eq!(
 9260                view.text(cx),
 9261                "
 9262                {a
 9263
 9264                /*
 9265                *
 9266                "
 9267                .unindent()
 9268            );
 9269
 9270            view.undo(&Undo, cx);
 9271            view.change_selections(None, cx, |s| {
 9272                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 9273            });
 9274            view.handle_input("{", cx);
 9275            assert_eq!(
 9276                view.text(cx),
 9277                "
 9278                {a}
 9279
 9280                /*
 9281                *
 9282                "
 9283                .unindent()
 9284            );
 9285            assert_eq!(
 9286                view.selections.display_ranges(cx),
 9287                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9288            );
 9289
 9290            view.undo(&Undo, cx);
 9291            view.handle_input("[", cx);
 9292            assert_eq!(
 9293                view.text(cx),
 9294                "
 9295                [a]
 9296                
 9297                /*
 9298                *
 9299                "
 9300                .unindent()
 9301            );
 9302            assert_eq!(
 9303                view.selections.display_ranges(cx),
 9304                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9305            );
 9306
 9307            view.undo(&Undo, cx);
 9308            view.change_selections(None, cx, |s| {
 9309                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9310            });
 9311            view.handle_input("[", cx);
 9312            assert_eq!(
 9313                view.text(cx),
 9314                "
 9315                a[
 9316                
 9317                /*
 9318                *
 9319                "
 9320                .unindent()
 9321            );
 9322            assert_eq!(
 9323                view.selections.display_ranges(cx),
 9324                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9325            );
 9326        });
 9327    }
 9328
 9329    #[gpui::test]
 9330    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9331        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9332        let language = Arc::new(Language::new(
 9333            LanguageConfig {
 9334                brackets: vec![BracketPair {
 9335                    start: "{".to_string(),
 9336                    end: "}".to_string(),
 9337                    close: true,
 9338                    newline: true,
 9339                }],
 9340                ..Default::default()
 9341            },
 9342            Some(tree_sitter_rust::language()),
 9343        ));
 9344
 9345        let text = r#"
 9346            a
 9347            b
 9348            c
 9349        "#
 9350        .unindent();
 9351
 9352        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9353        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9354        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9355        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9356            .await;
 9357
 9358        view.update(cx, |view, cx| {
 9359            view.change_selections(None, cx, |s| {
 9360                s.select_display_ranges([
 9361                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9362                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9363                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9364                ])
 9365            });
 9366
 9367            view.handle_input("{", cx);
 9368            view.handle_input("{", cx);
 9369            view.handle_input("{", cx);
 9370            assert_eq!(
 9371                view.text(cx),
 9372                "
 9373                {{{a}}}
 9374                {{{b}}}
 9375                {{{c}}}
 9376                "
 9377                .unindent()
 9378            );
 9379            assert_eq!(
 9380                view.selections.display_ranges(cx),
 9381                [
 9382                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9383                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9384                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9385                ]
 9386            );
 9387
 9388            view.undo(&Undo, cx);
 9389            assert_eq!(
 9390                view.text(cx),
 9391                "
 9392                a
 9393                b
 9394                c
 9395                "
 9396                .unindent()
 9397            );
 9398            assert_eq!(
 9399                view.selections.display_ranges(cx),
 9400                [
 9401                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9402                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9403                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9404                ]
 9405            );
 9406        });
 9407    }
 9408
 9409    #[gpui::test]
 9410    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9411        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9412        let language = Arc::new(Language::new(
 9413            LanguageConfig {
 9414                brackets: vec![BracketPair {
 9415                    start: "{".to_string(),
 9416                    end: "}".to_string(),
 9417                    close: true,
 9418                    newline: true,
 9419                }],
 9420                autoclose_before: "}".to_string(),
 9421                ..Default::default()
 9422            },
 9423            Some(tree_sitter_rust::language()),
 9424        ));
 9425
 9426        let text = r#"
 9427            a
 9428            b
 9429            c
 9430        "#
 9431        .unindent();
 9432
 9433        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9434        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9435        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9436        editor
 9437            .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9438            .await;
 9439
 9440        editor.update(cx, |editor, cx| {
 9441            editor.change_selections(None, cx, |s| {
 9442                s.select_ranges([
 9443                    Point::new(0, 1)..Point::new(0, 1),
 9444                    Point::new(1, 1)..Point::new(1, 1),
 9445                    Point::new(2, 1)..Point::new(2, 1),
 9446                ])
 9447            });
 9448
 9449            editor.handle_input("{", cx);
 9450            editor.handle_input("{", cx);
 9451            editor.handle_input("_", cx);
 9452            assert_eq!(
 9453                editor.text(cx),
 9454                "
 9455                a{{_}}
 9456                b{{_}}
 9457                c{{_}}
 9458                "
 9459                .unindent()
 9460            );
 9461            assert_eq!(
 9462                editor.selections.ranges::<Point>(cx),
 9463                [
 9464                    Point::new(0, 4)..Point::new(0, 4),
 9465                    Point::new(1, 4)..Point::new(1, 4),
 9466                    Point::new(2, 4)..Point::new(2, 4)
 9467                ]
 9468            );
 9469
 9470            editor.backspace(&Default::default(), cx);
 9471            editor.backspace(&Default::default(), cx);
 9472            assert_eq!(
 9473                editor.text(cx),
 9474                "
 9475                a{}
 9476                b{}
 9477                c{}
 9478                "
 9479                .unindent()
 9480            );
 9481            assert_eq!(
 9482                editor.selections.ranges::<Point>(cx),
 9483                [
 9484                    Point::new(0, 2)..Point::new(0, 2),
 9485                    Point::new(1, 2)..Point::new(1, 2),
 9486                    Point::new(2, 2)..Point::new(2, 2)
 9487                ]
 9488            );
 9489
 9490            editor.delete_to_previous_word_start(&Default::default(), cx);
 9491            assert_eq!(
 9492                editor.text(cx),
 9493                "
 9494                a
 9495                b
 9496                c
 9497                "
 9498                .unindent()
 9499            );
 9500            assert_eq!(
 9501                editor.selections.ranges::<Point>(cx),
 9502                [
 9503                    Point::new(0, 1)..Point::new(0, 1),
 9504                    Point::new(1, 1)..Point::new(1, 1),
 9505                    Point::new(2, 1)..Point::new(2, 1)
 9506                ]
 9507            );
 9508        });
 9509    }
 9510
 9511    #[gpui::test]
 9512    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9513        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9514
 9515        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 9516            a.| b
 9517            a.| b
 9518            a.| b"});
 9519        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9520        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9521
 9522        editor.update(cx, |editor, cx| {
 9523            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9524
 9525            editor
 9526                .insert_snippet(&insertion_ranges, snippet, cx)
 9527                .unwrap();
 9528
 9529            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 9530                let range_markers = ('<', '>');
 9531                let (expected_text, mut selection_ranges_lookup) =
 9532                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 9533                let selection_ranges = selection_ranges_lookup
 9534                    .remove(&range_markers.into())
 9535                    .unwrap();
 9536                assert_eq!(editor.text(cx), expected_text);
 9537                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9538            }
 9539            assert(
 9540                editor,
 9541                cx,
 9542                indoc! {"
 9543                    a.f(<one>, two, <three>) b
 9544                    a.f(<one>, two, <three>) b
 9545                    a.f(<one>, two, <three>) b"},
 9546            );
 9547
 9548            // Can't move earlier than the first tab stop
 9549            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9550            assert(
 9551                editor,
 9552                cx,
 9553                indoc! {"
 9554                    a.f(<one>, two, <three>) b
 9555                    a.f(<one>, two, <three>) b
 9556                    a.f(<one>, two, <three>) b"},
 9557            );
 9558
 9559            assert!(editor.move_to_next_snippet_tabstop(cx));
 9560            assert(
 9561                editor,
 9562                cx,
 9563                indoc! {"
 9564                    a.f(one, <two>, three) b
 9565                    a.f(one, <two>, three) b
 9566                    a.f(one, <two>, three) b"},
 9567            );
 9568
 9569            editor.move_to_prev_snippet_tabstop(cx);
 9570            assert(
 9571                editor,
 9572                cx,
 9573                indoc! {"
 9574                    a.f(<one>, two, <three>) b
 9575                    a.f(<one>, two, <three>) b
 9576                    a.f(<one>, two, <three>) b"},
 9577            );
 9578
 9579            assert!(editor.move_to_next_snippet_tabstop(cx));
 9580            assert(
 9581                editor,
 9582                cx,
 9583                indoc! {"
 9584                    a.f(one, <two>, three) b
 9585                    a.f(one, <two>, three) b
 9586                    a.f(one, <two>, three) b"},
 9587            );
 9588            assert!(editor.move_to_next_snippet_tabstop(cx));
 9589            assert(
 9590                editor,
 9591                cx,
 9592                indoc! {"
 9593                    a.f(one, two, three)<> b
 9594                    a.f(one, two, three)<> b
 9595                    a.f(one, two, three)<> b"},
 9596            );
 9597
 9598            // As soon as the last tab stop is reached, snippet state is gone
 9599            editor.move_to_prev_snippet_tabstop(cx);
 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    }
 9610
 9611    #[gpui::test]
 9612    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9613        cx.foreground().forbid_parking();
 9614
 9615        let mut language = Language::new(
 9616            LanguageConfig {
 9617                name: "Rust".into(),
 9618                path_suffixes: vec!["rs".to_string()],
 9619                ..Default::default()
 9620            },
 9621            Some(tree_sitter_rust::language()),
 9622        );
 9623        let mut fake_servers = language
 9624            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9625                capabilities: lsp::ServerCapabilities {
 9626                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9627                    ..Default::default()
 9628                },
 9629                ..Default::default()
 9630            }))
 9631            .await;
 9632
 9633        let fs = FakeFs::new(cx.background().clone());
 9634        fs.insert_file("/file.rs", Default::default()).await;
 9635
 9636        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9637        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9638        let buffer = project
 9639            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9640            .await
 9641            .unwrap();
 9642
 9643        cx.foreground().start_waiting();
 9644        let fake_server = fake_servers.next().await.unwrap();
 9645
 9646        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9647        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9648        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9649        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9650
 9651        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9652        fake_server
 9653            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9654                assert_eq!(
 9655                    params.text_document.uri,
 9656                    lsp::Url::from_file_path("/file.rs").unwrap()
 9657                );
 9658                assert_eq!(params.options.tab_size, 4);
 9659                Ok(Some(vec![lsp::TextEdit::new(
 9660                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9661                    ", ".to_string(),
 9662                )]))
 9663            })
 9664            .next()
 9665            .await;
 9666        cx.foreground().start_waiting();
 9667        save.await.unwrap();
 9668        assert_eq!(
 9669            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9670            "one, two\nthree\n"
 9671        );
 9672        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9673
 9674        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9675        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9676
 9677        // Ensure we can still save even if formatting hangs.
 9678        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9679            assert_eq!(
 9680                params.text_document.uri,
 9681                lsp::Url::from_file_path("/file.rs").unwrap()
 9682            );
 9683            futures::future::pending::<()>().await;
 9684            unreachable!()
 9685        });
 9686        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9687        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9688        cx.foreground().start_waiting();
 9689        save.await.unwrap();
 9690        assert_eq!(
 9691            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9692            "one\ntwo\nthree\n"
 9693        );
 9694        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9695
 9696        // Set rust language override and assert overriden tabsize is sent to language server
 9697        cx.update(|cx| {
 9698            cx.update_global::<Settings, _, _>(|settings, _| {
 9699                settings.language_overrides.insert(
 9700                    "Rust".into(),
 9701                    EditorSettings {
 9702                        tab_size: Some(8.try_into().unwrap()),
 9703                        ..Default::default()
 9704                    },
 9705                );
 9706            })
 9707        });
 9708
 9709        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9710        fake_server
 9711            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9712                assert_eq!(
 9713                    params.text_document.uri,
 9714                    lsp::Url::from_file_path("/file.rs").unwrap()
 9715                );
 9716                assert_eq!(params.options.tab_size, 8);
 9717                Ok(Some(vec![]))
 9718            })
 9719            .next()
 9720            .await;
 9721        cx.foreground().start_waiting();
 9722        save.await.unwrap();
 9723    }
 9724
 9725    #[gpui::test]
 9726    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
 9727        cx.foreground().forbid_parking();
 9728
 9729        let mut language = Language::new(
 9730            LanguageConfig {
 9731                name: "Rust".into(),
 9732                path_suffixes: vec!["rs".to_string()],
 9733                ..Default::default()
 9734            },
 9735            Some(tree_sitter_rust::language()),
 9736        );
 9737        let mut fake_servers = language
 9738            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9739                capabilities: lsp::ServerCapabilities {
 9740                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
 9741                    ..Default::default()
 9742                },
 9743                ..Default::default()
 9744            }))
 9745            .await;
 9746
 9747        let fs = FakeFs::new(cx.background().clone());
 9748        fs.insert_file("/file.rs", Default::default()).await;
 9749
 9750        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9751        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9752        let buffer = project
 9753            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9754            .await
 9755            .unwrap();
 9756
 9757        cx.foreground().start_waiting();
 9758        let fake_server = fake_servers.next().await.unwrap();
 9759
 9760        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9761        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9762        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9763        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9764
 9765        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9766        fake_server
 9767            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9768                assert_eq!(
 9769                    params.text_document.uri,
 9770                    lsp::Url::from_file_path("/file.rs").unwrap()
 9771                );
 9772                assert_eq!(params.options.tab_size, 4);
 9773                Ok(Some(vec![lsp::TextEdit::new(
 9774                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9775                    ", ".to_string(),
 9776                )]))
 9777            })
 9778            .next()
 9779            .await;
 9780        cx.foreground().start_waiting();
 9781        save.await.unwrap();
 9782        assert_eq!(
 9783            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9784            "one, two\nthree\n"
 9785        );
 9786        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9787
 9788        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9789        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9790
 9791        // Ensure we can still save even if formatting hangs.
 9792        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
 9793            move |params, _| async move {
 9794                assert_eq!(
 9795                    params.text_document.uri,
 9796                    lsp::Url::from_file_path("/file.rs").unwrap()
 9797                );
 9798                futures::future::pending::<()>().await;
 9799                unreachable!()
 9800            },
 9801        );
 9802        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9803        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9804        cx.foreground().start_waiting();
 9805        save.await.unwrap();
 9806        assert_eq!(
 9807            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9808            "one\ntwo\nthree\n"
 9809        );
 9810        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9811
 9812        // Set rust language override and assert overriden tabsize is sent to language server
 9813        cx.update(|cx| {
 9814            cx.update_global::<Settings, _, _>(|settings, _| {
 9815                settings.language_overrides.insert(
 9816                    "Rust".into(),
 9817                    EditorSettings {
 9818                        tab_size: Some(8.try_into().unwrap()),
 9819                        ..Default::default()
 9820                    },
 9821                );
 9822            })
 9823        });
 9824
 9825        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9826        fake_server
 9827            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9828                assert_eq!(
 9829                    params.text_document.uri,
 9830                    lsp::Url::from_file_path("/file.rs").unwrap()
 9831                );
 9832                assert_eq!(params.options.tab_size, 8);
 9833                Ok(Some(vec![]))
 9834            })
 9835            .next()
 9836            .await;
 9837        cx.foreground().start_waiting();
 9838        save.await.unwrap();
 9839    }
 9840
 9841    #[gpui::test]
 9842    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9843        let mut cx = EditorLspTestContext::new_rust(
 9844            lsp::ServerCapabilities {
 9845                completion_provider: Some(lsp::CompletionOptions {
 9846                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9847                    ..Default::default()
 9848                }),
 9849                ..Default::default()
 9850            },
 9851            cx,
 9852        )
 9853        .await;
 9854
 9855        cx.set_state(indoc! {"
 9856            one|
 9857            two
 9858            three"});
 9859        cx.simulate_input(".");
 9860        handle_completion_request(
 9861            &mut cx,
 9862            indoc! {"
 9863                one.|<>
 9864                two
 9865                three"},
 9866            vec!["first_completion", "second_completion"],
 9867        )
 9868        .await;
 9869        cx.condition(|editor, _| editor.context_menu_visible())
 9870            .await;
 9871        let apply_additional_edits = cx.update_editor(|editor, cx| {
 9872            editor.move_down(&MoveDown, cx);
 9873            editor
 9874                .confirm_completion(&ConfirmCompletion::default(), cx)
 9875                .unwrap()
 9876        });
 9877        cx.assert_editor_state(indoc! {"
 9878            one.second_completion|
 9879            two
 9880            three"});
 9881
 9882        handle_resolve_completion_request(
 9883            &mut cx,
 9884            Some((
 9885                indoc! {"
 9886                    one.second_completion
 9887                    two
 9888                    three<>"},
 9889                "\nadditional edit",
 9890            )),
 9891        )
 9892        .await;
 9893        apply_additional_edits.await.unwrap();
 9894        cx.assert_editor_state(indoc! {"
 9895            one.second_completion|
 9896            two
 9897            three
 9898            additional edit"});
 9899
 9900        cx.set_state(indoc! {"
 9901            one.second_completion
 9902            two|
 9903            three|
 9904            additional edit"});
 9905        cx.simulate_input(" ");
 9906        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9907        cx.simulate_input("s");
 9908        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9909
 9910        cx.assert_editor_state(indoc! {"
 9911            one.second_completion
 9912            two s|
 9913            three s|
 9914            additional edit"});
 9915        handle_completion_request(
 9916            &mut cx,
 9917            indoc! {"
 9918                one.second_completion
 9919                two s
 9920                three <s|>
 9921                additional edit"},
 9922            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
 9923        )
 9924        .await;
 9925        cx.condition(|editor, _| editor.context_menu_visible())
 9926            .await;
 9927
 9928        cx.simulate_input("i");
 9929
 9930        handle_completion_request(
 9931            &mut cx,
 9932            indoc! {"
 9933                one.second_completion
 9934                two si
 9935                three <si|>
 9936                additional edit"},
 9937            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
 9938        )
 9939        .await;
 9940        cx.condition(|editor, _| editor.context_menu_visible())
 9941            .await;
 9942
 9943        let apply_additional_edits = cx.update_editor(|editor, cx| {
 9944            editor
 9945                .confirm_completion(&ConfirmCompletion::default(), cx)
 9946                .unwrap()
 9947        });
 9948        cx.assert_editor_state(indoc! {"
 9949            one.second_completion
 9950            two sixth_completion|
 9951            three sixth_completion|
 9952            additional edit"});
 9953
 9954        handle_resolve_completion_request(&mut cx, None).await;
 9955        apply_additional_edits.await.unwrap();
 9956
 9957        cx.update(|cx| {
 9958            cx.update_global::<Settings, _, _>(|settings, _| {
 9959                settings.show_completions_on_input = false;
 9960            })
 9961        });
 9962        cx.set_state("editor|");
 9963        cx.simulate_input(".");
 9964        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9965        cx.simulate_input("c");
 9966        cx.simulate_input("l");
 9967        cx.simulate_input("o");
 9968        cx.assert_editor_state("editor.clo|");
 9969        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9970        cx.update_editor(|editor, cx| {
 9971            editor.show_completions(&ShowCompletions, cx);
 9972        });
 9973        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
 9974        cx.condition(|editor, _| editor.context_menu_visible())
 9975            .await;
 9976        let apply_additional_edits = cx.update_editor(|editor, cx| {
 9977            editor
 9978                .confirm_completion(&ConfirmCompletion::default(), cx)
 9979                .unwrap()
 9980        });
 9981        cx.assert_editor_state("editor.close|");
 9982        handle_resolve_completion_request(&mut cx, None).await;
 9983        apply_additional_edits.await.unwrap();
 9984
 9985        // Handle completion request passing a marked string specifying where the completion
 9986        // should be triggered from using '|' character, what range should be replaced, and what completions
 9987        // should be returned using '<' and '>' to delimit the range
 9988        async fn handle_completion_request<'a>(
 9989            cx: &mut EditorLspTestContext<'a>,
 9990            marked_string: &str,
 9991            completions: Vec<&'static str>,
 9992        ) {
 9993            let complete_from_marker: TextRangeMarker = '|'.into();
 9994            let replace_range_marker: TextRangeMarker = ('<', '>').into();
 9995            let (_, mut marked_ranges) = marked_text_ranges_by(
 9996                marked_string,
 9997                vec![complete_from_marker.clone(), replace_range_marker.clone()],
 9998            );
 9999
10000            let complete_from_position =
10001                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
10002            let replace_range =
10003                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10004
10005            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
10006                let completions = completions.clone();
10007                async move {
10008                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
10009                    assert_eq!(
10010                        params.text_document_position.position,
10011                        complete_from_position
10012                    );
10013                    Ok(Some(lsp::CompletionResponse::Array(
10014                        completions
10015                            .iter()
10016                            .map(|completion_text| lsp::CompletionItem {
10017                                label: completion_text.to_string(),
10018                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
10019                                    range: replace_range.clone(),
10020                                    new_text: completion_text.to_string(),
10021                                })),
10022                                ..Default::default()
10023                            })
10024                            .collect(),
10025                    )))
10026                }
10027            })
10028            .next()
10029            .await;
10030        }
10031
10032        async fn handle_resolve_completion_request<'a>(
10033            cx: &mut EditorLspTestContext<'a>,
10034            edit: Option<(&'static str, &'static str)>,
10035        ) {
10036            let edit = edit.map(|(marked_string, new_text)| {
10037                let replace_range_marker: TextRangeMarker = ('<', '>').into();
10038                let (_, mut marked_ranges) =
10039                    marked_text_ranges_by(marked_string, vec![replace_range_marker.clone()]);
10040
10041                let replace_range = cx
10042                    .to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10043
10044                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
10045            });
10046
10047            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
10048                let edit = edit.clone();
10049                async move {
10050                    Ok(lsp::CompletionItem {
10051                        additional_text_edits: edit,
10052                        ..Default::default()
10053                    })
10054                }
10055            })
10056            .next()
10057            .await;
10058        }
10059    }
10060
10061    #[gpui::test]
10062    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
10063        cx.update(|cx| cx.set_global(Settings::test(cx)));
10064        let language = Arc::new(Language::new(
10065            LanguageConfig {
10066                line_comment: Some("// ".to_string()),
10067                ..Default::default()
10068            },
10069            Some(tree_sitter_rust::language()),
10070        ));
10071
10072        let text = "
10073            fn a() {
10074                //b();
10075                // c();
10076                //  d();
10077            }
10078        "
10079        .unindent();
10080
10081        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10082        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10083        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10084
10085        view.update(cx, |editor, cx| {
10086            // If multiple selections intersect a line, the line is only
10087            // toggled once.
10088            editor.change_selections(None, cx, |s| {
10089                s.select_display_ranges([
10090                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
10091                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
10092                ])
10093            });
10094            editor.toggle_comments(&ToggleComments, cx);
10095            assert_eq!(
10096                editor.text(cx),
10097                "
10098                    fn a() {
10099                        b();
10100                        c();
10101                         d();
10102                    }
10103                "
10104                .unindent()
10105            );
10106
10107            // The comment prefix is inserted at the same column for every line
10108            // in a selection.
10109            editor.change_selections(None, cx, |s| {
10110                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
10111            });
10112            editor.toggle_comments(&ToggleComments, cx);
10113            assert_eq!(
10114                editor.text(cx),
10115                "
10116                    fn a() {
10117                        // b();
10118                        // c();
10119                        //  d();
10120                    }
10121                "
10122                .unindent()
10123            );
10124
10125            // If a selection ends at the beginning of a line, that line is not toggled.
10126            editor.change_selections(None, cx, |s| {
10127                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
10128            });
10129            editor.toggle_comments(&ToggleComments, cx);
10130            assert_eq!(
10131                editor.text(cx),
10132                "
10133                        fn a() {
10134                            // b();
10135                            c();
10136                            //  d();
10137                        }
10138                    "
10139                .unindent()
10140            );
10141        });
10142    }
10143
10144    #[gpui::test]
10145    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
10146        cx.set_global(Settings::test(cx));
10147        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10148        let multibuffer = cx.add_model(|cx| {
10149            let mut multibuffer = MultiBuffer::new(0);
10150            multibuffer.push_excerpts(
10151                buffer.clone(),
10152                [
10153                    ExcerptRange {
10154                        context: Point::new(0, 0)..Point::new(0, 4),
10155                        primary: None,
10156                    },
10157                    ExcerptRange {
10158                        context: Point::new(1, 0)..Point::new(1, 4),
10159                        primary: None,
10160                    },
10161                ],
10162                cx,
10163            );
10164            multibuffer
10165        });
10166
10167        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
10168
10169        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10170        view.update(cx, |view, cx| {
10171            assert_eq!(view.text(cx), "aaaa\nbbbb");
10172            view.change_selections(None, cx, |s| {
10173                s.select_ranges([
10174                    Point::new(0, 0)..Point::new(0, 0),
10175                    Point::new(1, 0)..Point::new(1, 0),
10176                ])
10177            });
10178
10179            view.handle_input("X", cx);
10180            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
10181            assert_eq!(
10182                view.selections.ranges(cx),
10183                [
10184                    Point::new(0, 1)..Point::new(0, 1),
10185                    Point::new(1, 1)..Point::new(1, 1),
10186                ]
10187            )
10188        });
10189    }
10190
10191    #[gpui::test]
10192    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
10193        cx.set_global(Settings::test(cx));
10194        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
10195                [aaaa
10196                (bbbb]
10197                cccc)"});
10198        let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
10199            context,
10200            primary: None,
10201        });
10202        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
10203        let multibuffer = cx.add_model(|cx| {
10204            let mut multibuffer = MultiBuffer::new(0);
10205            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
10206            multibuffer
10207        });
10208
10209        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10210        view.update(cx, |view, cx| {
10211            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
10212                aaaa
10213                b|bbb
10214                b|bb|b
10215                cccc"});
10216            assert_eq!(view.text(cx), expected_text);
10217            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
10218
10219            view.handle_input("X", cx);
10220
10221            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10222                aaaa
10223                bX|bbXb
10224                bX|bbX|b
10225                cccc"});
10226            assert_eq!(view.text(cx), expected_text);
10227            assert_eq!(view.selections.ranges(cx), expected_selections);
10228
10229            view.newline(&Newline, cx);
10230            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10231                aaaa
10232                bX
10233                |bbX
10234                b
10235                bX
10236                |bbX
10237                |b
10238                cccc"});
10239            assert_eq!(view.text(cx), expected_text);
10240            assert_eq!(view.selections.ranges(cx), expected_selections);
10241        });
10242    }
10243
10244    #[gpui::test]
10245    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
10246        cx.set_global(Settings::test(cx));
10247        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10248        let mut excerpt1_id = None;
10249        let multibuffer = cx.add_model(|cx| {
10250            let mut multibuffer = MultiBuffer::new(0);
10251            excerpt1_id = multibuffer
10252                .push_excerpts(
10253                    buffer.clone(),
10254                    [
10255                        ExcerptRange {
10256                            context: Point::new(0, 0)..Point::new(1, 4),
10257                            primary: None,
10258                        },
10259                        ExcerptRange {
10260                            context: Point::new(1, 0)..Point::new(2, 4),
10261                            primary: None,
10262                        },
10263                    ],
10264                    cx,
10265                )
10266                .into_iter()
10267                .next();
10268            multibuffer
10269        });
10270        assert_eq!(
10271            multibuffer.read(cx).read(cx).text(),
10272            "aaaa\nbbbb\nbbbb\ncccc"
10273        );
10274        let (_, editor) = cx.add_window(Default::default(), |cx| {
10275            let mut editor = build_editor(multibuffer.clone(), cx);
10276            let snapshot = editor.snapshot(cx);
10277            editor.change_selections(None, cx, |s| {
10278                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
10279            });
10280            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
10281            assert_eq!(
10282                editor.selections.ranges(cx),
10283                [
10284                    Point::new(1, 3)..Point::new(1, 3),
10285                    Point::new(2, 1)..Point::new(2, 1),
10286                ]
10287            );
10288            editor
10289        });
10290
10291        // Refreshing selections is a no-op when excerpts haven't changed.
10292        editor.update(cx, |editor, cx| {
10293            editor.change_selections(None, cx, |s| {
10294                s.refresh();
10295            });
10296            assert_eq!(
10297                editor.selections.ranges(cx),
10298                [
10299                    Point::new(1, 3)..Point::new(1, 3),
10300                    Point::new(2, 1)..Point::new(2, 1),
10301                ]
10302            );
10303        });
10304
10305        multibuffer.update(cx, |multibuffer, cx| {
10306            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10307        });
10308        editor.update(cx, |editor, cx| {
10309            // Removing an excerpt causes the first selection to become degenerate.
10310            assert_eq!(
10311                editor.selections.ranges(cx),
10312                [
10313                    Point::new(0, 0)..Point::new(0, 0),
10314                    Point::new(0, 1)..Point::new(0, 1)
10315                ]
10316            );
10317
10318            // Refreshing selections will relocate the first selection to the original buffer
10319            // location.
10320            editor.change_selections(None, cx, |s| {
10321                s.refresh();
10322            });
10323            assert_eq!(
10324                editor.selections.ranges(cx),
10325                [
10326                    Point::new(0, 1)..Point::new(0, 1),
10327                    Point::new(0, 3)..Point::new(0, 3)
10328                ]
10329            );
10330            assert!(editor.selections.pending_anchor().is_some());
10331        });
10332    }
10333
10334    #[gpui::test]
10335    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10336        cx.set_global(Settings::test(cx));
10337        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10338        let mut excerpt1_id = None;
10339        let multibuffer = cx.add_model(|cx| {
10340            let mut multibuffer = MultiBuffer::new(0);
10341            excerpt1_id = multibuffer
10342                .push_excerpts(
10343                    buffer.clone(),
10344                    [
10345                        ExcerptRange {
10346                            context: Point::new(0, 0)..Point::new(1, 4),
10347                            primary: None,
10348                        },
10349                        ExcerptRange {
10350                            context: Point::new(1, 0)..Point::new(2, 4),
10351                            primary: None,
10352                        },
10353                    ],
10354                    cx,
10355                )
10356                .into_iter()
10357                .next();
10358            multibuffer
10359        });
10360        assert_eq!(
10361            multibuffer.read(cx).read(cx).text(),
10362            "aaaa\nbbbb\nbbbb\ncccc"
10363        );
10364        let (_, editor) = cx.add_window(Default::default(), |cx| {
10365            let mut editor = build_editor(multibuffer.clone(), cx);
10366            let snapshot = editor.snapshot(cx);
10367            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10368            assert_eq!(
10369                editor.selections.ranges(cx),
10370                [Point::new(1, 3)..Point::new(1, 3)]
10371            );
10372            editor
10373        });
10374
10375        multibuffer.update(cx, |multibuffer, cx| {
10376            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10377        });
10378        editor.update(cx, |editor, cx| {
10379            assert_eq!(
10380                editor.selections.ranges(cx),
10381                [Point::new(0, 0)..Point::new(0, 0)]
10382            );
10383
10384            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10385            editor.change_selections(None, cx, |s| {
10386                s.refresh();
10387            });
10388            assert_eq!(
10389                editor.selections.ranges(cx),
10390                [Point::new(0, 3)..Point::new(0, 3)]
10391            );
10392            assert!(editor.selections.pending_anchor().is_some());
10393        });
10394    }
10395
10396    #[gpui::test]
10397    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10398        cx.update(|cx| cx.set_global(Settings::test(cx)));
10399        let language = Arc::new(
10400            Language::new(
10401                LanguageConfig {
10402                    brackets: vec![
10403                        BracketPair {
10404                            start: "{".to_string(),
10405                            end: "}".to_string(),
10406                            close: true,
10407                            newline: true,
10408                        },
10409                        BracketPair {
10410                            start: "/* ".to_string(),
10411                            end: " */".to_string(),
10412                            close: true,
10413                            newline: true,
10414                        },
10415                    ],
10416                    ..Default::default()
10417                },
10418                Some(tree_sitter_rust::language()),
10419            )
10420            .with_indents_query("")
10421            .unwrap(),
10422        );
10423
10424        let text = concat!(
10425            "{   }\n",     // Suppress rustfmt
10426            "  x\n",       //
10427            "  /*   */\n", //
10428            "x\n",         //
10429            "{{} }\n",     //
10430        );
10431
10432        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10433        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10434        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10435        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10436            .await;
10437
10438        view.update(cx, |view, cx| {
10439            view.change_selections(None, cx, |s| {
10440                s.select_display_ranges([
10441                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10442                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10443                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10444                ])
10445            });
10446            view.newline(&Newline, cx);
10447
10448            assert_eq!(
10449                view.buffer().read(cx).read(cx).text(),
10450                concat!(
10451                    "{ \n",    // Suppress rustfmt
10452                    "\n",      //
10453                    "}\n",     //
10454                    "  x\n",   //
10455                    "  /* \n", //
10456                    "  \n",    //
10457                    "  */\n",  //
10458                    "x\n",     //
10459                    "{{} \n",  //
10460                    "}\n",     //
10461                )
10462            );
10463        });
10464    }
10465
10466    #[gpui::test]
10467    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10468        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10469
10470        cx.set_global(Settings::test(cx));
10471        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10472
10473        editor.update(cx, |editor, cx| {
10474            struct Type1;
10475            struct Type2;
10476
10477            let buffer = buffer.read(cx).snapshot(cx);
10478
10479            let anchor_range = |range: Range<Point>| {
10480                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10481            };
10482
10483            editor.highlight_background::<Type1>(
10484                vec![
10485                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10486                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10487                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10488                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10489                ],
10490                |_| Color::red(),
10491                cx,
10492            );
10493            editor.highlight_background::<Type2>(
10494                vec![
10495                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10496                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10497                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10498                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10499                ],
10500                |_| Color::green(),
10501                cx,
10502            );
10503
10504            let snapshot = editor.snapshot(cx);
10505            let mut highlighted_ranges = editor.background_highlights_in_range(
10506                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10507                &snapshot,
10508                cx.global::<Settings>().theme.as_ref(),
10509            );
10510            // Enforce a consistent ordering based on color without relying on the ordering of the
10511            // highlight's `TypeId` which is non-deterministic.
10512            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10513            assert_eq!(
10514                highlighted_ranges,
10515                &[
10516                    (
10517                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10518                        Color::green(),
10519                    ),
10520                    (
10521                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10522                        Color::green(),
10523                    ),
10524                    (
10525                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10526                        Color::red(),
10527                    ),
10528                    (
10529                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10530                        Color::red(),
10531                    ),
10532                ]
10533            );
10534            assert_eq!(
10535                editor.background_highlights_in_range(
10536                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10537                    &snapshot,
10538                    cx.global::<Settings>().theme.as_ref(),
10539                ),
10540                &[(
10541                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10542                    Color::red(),
10543                )]
10544            );
10545        });
10546    }
10547
10548    #[gpui::test]
10549    fn test_following(cx: &mut gpui::MutableAppContext) {
10550        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10551
10552        cx.set_global(Settings::test(cx));
10553
10554        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10555        let (_, follower) = cx.add_window(
10556            WindowOptions {
10557                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10558                ..Default::default()
10559            },
10560            |cx| build_editor(buffer.clone(), cx),
10561        );
10562
10563        let pending_update = Rc::new(RefCell::new(None));
10564        follower.update(cx, {
10565            let update = pending_update.clone();
10566            |_, cx| {
10567                cx.subscribe(&leader, move |_, leader, event, cx| {
10568                    leader
10569                        .read(cx)
10570                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10571                })
10572                .detach();
10573            }
10574        });
10575
10576        // Update the selections only
10577        leader.update(cx, |leader, cx| {
10578            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10579        });
10580        follower.update(cx, |follower, cx| {
10581            follower
10582                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10583                .unwrap();
10584        });
10585        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
10586
10587        // Update the scroll position only
10588        leader.update(cx, |leader, cx| {
10589            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10590        });
10591        follower.update(cx, |follower, cx| {
10592            follower
10593                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10594                .unwrap();
10595        });
10596        assert_eq!(
10597            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10598            vec2f(1.5, 3.5)
10599        );
10600
10601        // Update the selections and scroll position
10602        leader.update(cx, |leader, cx| {
10603            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
10604            leader.request_autoscroll(Autoscroll::Newest, cx);
10605            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10606        });
10607        follower.update(cx, |follower, cx| {
10608            let initial_scroll_position = follower.scroll_position(cx);
10609            follower
10610                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10611                .unwrap();
10612            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10613            assert!(follower.autoscroll_request.is_some());
10614        });
10615        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
10616
10617        // Creating a pending selection that precedes another selection
10618        leader.update(cx, |leader, cx| {
10619            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10620            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10621        });
10622        follower.update(cx, |follower, cx| {
10623            follower
10624                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10625                .unwrap();
10626        });
10627        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
10628
10629        // Extend the pending selection so that it surrounds another selection
10630        leader.update(cx, |leader, cx| {
10631            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10632        });
10633        follower.update(cx, |follower, cx| {
10634            follower
10635                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10636                .unwrap();
10637        });
10638        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
10639    }
10640
10641    #[test]
10642    fn test_combine_syntax_and_fuzzy_match_highlights() {
10643        let string = "abcdefghijklmnop";
10644        let syntax_ranges = [
10645            (
10646                0..3,
10647                HighlightStyle {
10648                    color: Some(Color::red()),
10649                    ..Default::default()
10650                },
10651            ),
10652            (
10653                4..8,
10654                HighlightStyle {
10655                    color: Some(Color::green()),
10656                    ..Default::default()
10657                },
10658            ),
10659        ];
10660        let match_indices = [4, 6, 7, 8];
10661        assert_eq!(
10662            combine_syntax_and_fuzzy_match_highlights(
10663                &string,
10664                Default::default(),
10665                syntax_ranges.into_iter(),
10666                &match_indices,
10667            ),
10668            &[
10669                (
10670                    0..3,
10671                    HighlightStyle {
10672                        color: Some(Color::red()),
10673                        ..Default::default()
10674                    },
10675                ),
10676                (
10677                    4..5,
10678                    HighlightStyle {
10679                        color: Some(Color::green()),
10680                        weight: Some(fonts::Weight::BOLD),
10681                        ..Default::default()
10682                    },
10683                ),
10684                (
10685                    5..6,
10686                    HighlightStyle {
10687                        color: Some(Color::green()),
10688                        ..Default::default()
10689                    },
10690                ),
10691                (
10692                    6..8,
10693                    HighlightStyle {
10694                        color: Some(Color::green()),
10695                        weight: Some(fonts::Weight::BOLD),
10696                        ..Default::default()
10697                    },
10698                ),
10699                (
10700                    8..9,
10701                    HighlightStyle {
10702                        weight: Some(fonts::Weight::BOLD),
10703                        ..Default::default()
10704                    },
10705                ),
10706            ]
10707        );
10708    }
10709
10710    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10711        let point = DisplayPoint::new(row as u32, column as u32);
10712        point..point
10713    }
10714
10715    fn assert_selection_ranges(
10716        marked_text: &str,
10717        selection_marker_pairs: Vec<(char, char)>,
10718        view: &mut Editor,
10719        cx: &mut ViewContext<Editor>,
10720    ) {
10721        let snapshot = view.snapshot(cx).display_snapshot;
10722        let mut marker_chars = Vec::new();
10723        for (start, end) in selection_marker_pairs.iter() {
10724            marker_chars.push(*start);
10725            marker_chars.push(*end);
10726        }
10727        let (_, markers) = marked_text_by(marked_text, marker_chars);
10728        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10729            .iter()
10730            .map(|(start, end)| {
10731                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10732                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10733                start..end
10734            })
10735            .collect();
10736        assert_eq!(
10737            view.selections.display_ranges(cx),
10738            &asserted_ranges[..],
10739            "Assert selections are {}",
10740            marked_text
10741        );
10742    }
10743}
10744
10745trait RangeExt<T> {
10746    fn sorted(&self) -> Range<T>;
10747    fn to_inclusive(&self) -> RangeInclusive<T>;
10748}
10749
10750impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10751    fn sorted(&self) -> Self {
10752        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10753    }
10754
10755    fn to_inclusive(&self) -> RangeInclusive<T> {
10756        self.start.clone()..=self.end.clone()
10757    }
10758}
10759
10760trait RangeToAnchorExt {
10761    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10762}
10763
10764impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10765    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10766        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10767    }
10768}