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