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