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