editor.rs

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