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