editor.rs

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