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, OffsetUtf16, Point, Selection, SelectionGoal,
   43    TransactionId,
   44};
   45use link_go_to_definition::LinkGoToDefinitionState;
   46pub use multi_buffer::{
   47    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
   48    ToPoint,
   49};
   50use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
   51use ordered_float::OrderedFloat;
   52use project::{LocationLink, Project, ProjectPath, ProjectTransaction};
   53use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
   54use serde::{Deserialize, Serialize};
   55use settings::Settings;
   56use smallvec::SmallVec;
   57use smol::Timer;
   58use snippet::Snippet;
   59use std::{
   60    any::TypeId,
   61    borrow::Cow,
   62    cmp::{self, Ordering, Reverse},
   63    mem,
   64    num::NonZeroU32,
   65    ops::{Deref, DerefMut, Range, RangeInclusive},
   66    sync::Arc,
   67    time::{Duration, Instant},
   68};
   69pub use sum_tree::Bias;
   70use theme::{DiagnosticStyle, Theme};
   71use util::{post_inc, ResultExt, TryFutureExt};
   72use workspace::{ItemNavHistory, Workspace};
   73
   74const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
   75const MAX_LINE_LEN: usize = 1024;
   76const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
   77const MAX_SELECTION_HISTORY_LEN: usize = 1024;
   78
   79#[derive(Clone, Deserialize, PartialEq)]
   80pub struct SelectNext {
   81    #[serde(default)]
   82    pub replace_newest: bool,
   83}
   84
   85#[derive(Clone, PartialEq)]
   86pub struct 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_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
 5881        Some(
 5882            self.buffer
 5883                .read(cx)
 5884                .read(cx)
 5885                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 5886                .collect(),
 5887        )
 5888    }
 5889
 5890    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 5891        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 5892        Some(range.start.0..range.end.0)
 5893    }
 5894
 5895    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 5896        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 5897        let snapshot = self.buffer.read(cx).read(cx);
 5898        let range_utf16 =
 5899            range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot);
 5900        Some(range_utf16.start.0..range_utf16.end.0)
 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_utf16: Option<Range<usize>>,
 5910        text: &str,
 5911        cx: &mut ViewContext<Self>,
 5912    ) {
 5913        self.transact(cx, |this, cx| {
 5914            if let Some(range) = range_utf16.or_else(|| this.marked_text_range(cx)) {
 5915                this.change_selections(None, cx, |selections| {
 5916                    selections.select_ranges([OffsetUtf16(range.start)..OffsetUtf16(range.end)])
 5917                });
 5918            }
 5919            this.handle_input(text, cx);
 5920            this.unmark_text(cx);
 5921        });
 5922    }
 5923
 5924    fn replace_and_mark_text_in_range(
 5925        &mut self,
 5926        range_utf16: Option<Range<usize>>,
 5927        text: &str,
 5928        new_selected_range_utf16: Option<Range<usize>>,
 5929        cx: &mut ViewContext<Self>,
 5930    ) {
 5931        self.transact(cx, |this, cx| {
 5932            let range_to_replace = if let Some(mut marked_range) = this.marked_text_range(cx) {
 5933                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 5934                    marked_range.end = marked_range.start + relative_range_utf16.end;
 5935                    marked_range.start += relative_range_utf16.start;
 5936                }
 5937                Some(marked_range)
 5938            } else if let Some(range_utf16) = range_utf16 {
 5939                Some(range_utf16)
 5940            } else {
 5941                None
 5942            };
 5943
 5944            if let Some(range) = range_to_replace {
 5945                this.change_selections(None, cx, |s| {
 5946                    s.select_ranges([OffsetUtf16(range.start)..OffsetUtf16(range.end)])
 5947                });
 5948            }
 5949
 5950            let selection = this.selections.newest_anchor();
 5951            let marked_range = {
 5952                let snapshot = this.buffer.read(cx).read(cx);
 5953                selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 5954            };
 5955
 5956            if text.is_empty() {
 5957                this.unmark_text(cx);
 5958            } else {
 5959                this.highlight_text::<InputComposition>(
 5960                    vec![marked_range.clone()],
 5961                    this.style(cx).composition_mark,
 5962                    cx,
 5963                );
 5964            }
 5965
 5966            this.handle_input(text, cx);
 5967
 5968            if let Some(mut new_selected_range) = new_selected_range_utf16 {
 5969                let snapshot = this.buffer.read(cx).read(cx);
 5970                let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 5971                new_selected_range.start += insertion_start;
 5972                new_selected_range.end += insertion_start;
 5973                drop(snapshot);
 5974                this.change_selections(None, cx, |selections| {
 5975                    selections
 5976                        .select_ranges([OffsetUtf16(new_selected_range.start)
 5977                            ..OffsetUtf16(new_selected_range.end)])
 5978                });
 5979            }
 5980        });
 5981    }
 5982}
 5983
 5984fn build_style(
 5985    settings: &Settings,
 5986    get_field_editor_theme: Option<GetFieldEditorTheme>,
 5987    override_text_style: Option<&OverrideTextStyle>,
 5988    cx: &AppContext,
 5989) -> EditorStyle {
 5990    let font_cache = cx.font_cache();
 5991
 5992    let mut theme = settings.theme.editor.clone();
 5993    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 5994        let field_editor_theme = get_field_editor_theme(&settings.theme);
 5995        theme.text_color = field_editor_theme.text.color;
 5996        theme.selection = field_editor_theme.selection;
 5997        theme.background = field_editor_theme
 5998            .container
 5999            .background_color
 6000            .unwrap_or_default();
 6001        EditorStyle {
 6002            text: field_editor_theme.text,
 6003            placeholder_text: field_editor_theme.placeholder_text,
 6004            theme,
 6005        }
 6006    } else {
 6007        let font_family_id = settings.buffer_font_family;
 6008        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6009        let font_properties = Default::default();
 6010        let font_id = font_cache
 6011            .select_font(font_family_id, &font_properties)
 6012            .unwrap();
 6013        let font_size = settings.buffer_font_size;
 6014        EditorStyle {
 6015            text: TextStyle {
 6016                color: settings.theme.editor.text_color,
 6017                font_family_name,
 6018                font_family_id,
 6019                font_id,
 6020                font_size,
 6021                font_properties,
 6022                underline: Default::default(),
 6023            },
 6024            placeholder_text: None,
 6025            theme,
 6026        }
 6027    };
 6028
 6029    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6030        if let Some(highlighted) = style
 6031            .text
 6032            .clone()
 6033            .highlight(highlight_style, font_cache)
 6034            .log_err()
 6035        {
 6036            style.text = highlighted;
 6037        }
 6038    }
 6039
 6040    style
 6041}
 6042
 6043trait SelectionExt {
 6044    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6045    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6046    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6047    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6048        -> Range<u32>;
 6049}
 6050
 6051impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6052    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6053        let start = self.start.to_point(buffer);
 6054        let end = self.end.to_point(buffer);
 6055        if self.reversed {
 6056            end..start
 6057        } else {
 6058            start..end
 6059        }
 6060    }
 6061
 6062    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6063        let start = self.start.to_offset(buffer);
 6064        let end = self.end.to_offset(buffer);
 6065        if self.reversed {
 6066            end..start
 6067        } else {
 6068            start..end
 6069        }
 6070    }
 6071
 6072    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6073        let start = self
 6074            .start
 6075            .to_point(&map.buffer_snapshot)
 6076            .to_display_point(map);
 6077        let end = self
 6078            .end
 6079            .to_point(&map.buffer_snapshot)
 6080            .to_display_point(map);
 6081        if self.reversed {
 6082            end..start
 6083        } else {
 6084            start..end
 6085        }
 6086    }
 6087
 6088    fn spanned_rows(
 6089        &self,
 6090        include_end_if_at_line_start: bool,
 6091        map: &DisplaySnapshot,
 6092    ) -> Range<u32> {
 6093        let start = self.start.to_point(&map.buffer_snapshot);
 6094        let mut end = self.end.to_point(&map.buffer_snapshot);
 6095        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6096            end.row -= 1;
 6097        }
 6098
 6099        let buffer_start = map.prev_line_boundary(start).0;
 6100        let buffer_end = map.next_line_boundary(end).0;
 6101        buffer_start.row..buffer_end.row + 1
 6102    }
 6103}
 6104
 6105impl<T: InvalidationRegion> InvalidationStack<T> {
 6106    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6107    where
 6108        S: Clone + ToOffset,
 6109    {
 6110        while let Some(region) = self.last() {
 6111            let all_selections_inside_invalidation_ranges =
 6112                if selections.len() == region.ranges().len() {
 6113                    selections
 6114                        .iter()
 6115                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6116                        .all(|(selection, invalidation_range)| {
 6117                            let head = selection.head().to_offset(&buffer);
 6118                            invalidation_range.start <= head && invalidation_range.end >= head
 6119                        })
 6120                } else {
 6121                    false
 6122                };
 6123
 6124            if all_selections_inside_invalidation_ranges {
 6125                break;
 6126            } else {
 6127                self.pop();
 6128            }
 6129        }
 6130    }
 6131}
 6132
 6133impl<T> Default for InvalidationStack<T> {
 6134    fn default() -> Self {
 6135        Self(Default::default())
 6136    }
 6137}
 6138
 6139impl<T> Deref for InvalidationStack<T> {
 6140    type Target = Vec<T>;
 6141
 6142    fn deref(&self) -> &Self::Target {
 6143        &self.0
 6144    }
 6145}
 6146
 6147impl<T> DerefMut for InvalidationStack<T> {
 6148    fn deref_mut(&mut self) -> &mut Self::Target {
 6149        &mut self.0
 6150    }
 6151}
 6152
 6153impl InvalidationRegion for BracketPairState {
 6154    fn ranges(&self) -> &[Range<Anchor>] {
 6155        &self.ranges
 6156    }
 6157}
 6158
 6159impl InvalidationRegion for SnippetState {
 6160    fn ranges(&self) -> &[Range<Anchor>] {
 6161        &self.ranges[self.active_index]
 6162    }
 6163}
 6164
 6165impl Deref for EditorStyle {
 6166    type Target = theme::Editor;
 6167
 6168    fn deref(&self) -> &Self::Target {
 6169        &self.theme
 6170    }
 6171}
 6172
 6173pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6174    let mut highlighted_lines = Vec::new();
 6175    for line in diagnostic.message.lines() {
 6176        highlighted_lines.push(highlight_diagnostic_message(line));
 6177    }
 6178
 6179    Arc::new(move |cx: &mut BlockContext| {
 6180        let settings = cx.global::<Settings>();
 6181        let theme = &settings.theme.editor;
 6182        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6183        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6184        Flex::column()
 6185            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6186                Label::new(
 6187                    line.clone(),
 6188                    style.message.clone().with_font_size(font_size),
 6189                )
 6190                .with_highlights(highlights.clone())
 6191                .contained()
 6192                .with_margin_left(cx.anchor_x)
 6193                .boxed()
 6194            }))
 6195            .aligned()
 6196            .left()
 6197            .boxed()
 6198    })
 6199}
 6200
 6201pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6202    let mut message_without_backticks = String::new();
 6203    let mut prev_offset = 0;
 6204    let mut inside_block = false;
 6205    let mut highlights = Vec::new();
 6206    for (match_ix, (offset, _)) in message
 6207        .match_indices('`')
 6208        .chain([(message.len(), "")])
 6209        .enumerate()
 6210    {
 6211        message_without_backticks.push_str(&message[prev_offset..offset]);
 6212        if inside_block {
 6213            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6214        }
 6215
 6216        inside_block = !inside_block;
 6217        prev_offset = offset + 1;
 6218    }
 6219
 6220    (message_without_backticks, highlights)
 6221}
 6222
 6223pub fn diagnostic_style(
 6224    severity: DiagnosticSeverity,
 6225    valid: bool,
 6226    theme: &theme::Editor,
 6227) -> DiagnosticStyle {
 6228    match (severity, valid) {
 6229        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6230        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6231        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6232        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6233        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6234        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6235        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6236        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6237        _ => theme.invalid_hint_diagnostic.clone(),
 6238    }
 6239}
 6240
 6241pub fn combine_syntax_and_fuzzy_match_highlights(
 6242    text: &str,
 6243    default_style: HighlightStyle,
 6244    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6245    match_indices: &[usize],
 6246) -> Vec<(Range<usize>, HighlightStyle)> {
 6247    let mut result = Vec::new();
 6248    let mut match_indices = match_indices.iter().copied().peekable();
 6249
 6250    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6251    {
 6252        syntax_highlight.weight = None;
 6253
 6254        // Add highlights for any fuzzy match characters before the next
 6255        // syntax highlight range.
 6256        while let Some(&match_index) = match_indices.peek() {
 6257            if match_index >= range.start {
 6258                break;
 6259            }
 6260            match_indices.next();
 6261            let end_index = char_ix_after(match_index, text);
 6262            let mut match_style = default_style;
 6263            match_style.weight = Some(fonts::Weight::BOLD);
 6264            result.push((match_index..end_index, match_style));
 6265        }
 6266
 6267        if range.start == usize::MAX {
 6268            break;
 6269        }
 6270
 6271        // Add highlights for any fuzzy match characters within the
 6272        // syntax highlight range.
 6273        let mut offset = range.start;
 6274        while let Some(&match_index) = match_indices.peek() {
 6275            if match_index >= range.end {
 6276                break;
 6277            }
 6278
 6279            match_indices.next();
 6280            if match_index > offset {
 6281                result.push((offset..match_index, syntax_highlight));
 6282            }
 6283
 6284            let mut end_index = char_ix_after(match_index, text);
 6285            while let Some(&next_match_index) = match_indices.peek() {
 6286                if next_match_index == end_index && next_match_index < range.end {
 6287                    end_index = char_ix_after(next_match_index, text);
 6288                    match_indices.next();
 6289                } else {
 6290                    break;
 6291                }
 6292            }
 6293
 6294            let mut match_style = syntax_highlight;
 6295            match_style.weight = Some(fonts::Weight::BOLD);
 6296            result.push((match_index..end_index, match_style));
 6297            offset = end_index;
 6298        }
 6299
 6300        if offset < range.end {
 6301            result.push((offset..range.end, syntax_highlight));
 6302        }
 6303    }
 6304
 6305    fn char_ix_after(ix: usize, text: &str) -> usize {
 6306        ix + text[ix..].chars().next().unwrap().len_utf8()
 6307    }
 6308
 6309    result
 6310}
 6311
 6312pub fn styled_runs_for_code_label<'a>(
 6313    label: &'a CodeLabel,
 6314    syntax_theme: &'a theme::SyntaxTheme,
 6315) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6316    let fade_out = HighlightStyle {
 6317        fade_out: Some(0.35),
 6318        ..Default::default()
 6319    };
 6320
 6321    let mut prev_end = label.filter_range.end;
 6322    label
 6323        .runs
 6324        .iter()
 6325        .enumerate()
 6326        .flat_map(move |(ix, (range, highlight_id))| {
 6327            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6328                style
 6329            } else {
 6330                return Default::default();
 6331            };
 6332            let mut muted_style = style.clone();
 6333            muted_style.highlight(fade_out);
 6334
 6335            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6336            if range.start >= label.filter_range.end {
 6337                if range.start > prev_end {
 6338                    runs.push((prev_end..range.start, fade_out));
 6339                }
 6340                runs.push((range.clone(), muted_style));
 6341            } else if range.end <= label.filter_range.end {
 6342                runs.push((range.clone(), style));
 6343            } else {
 6344                runs.push((range.start..label.filter_range.end, style));
 6345                runs.push((label.filter_range.end..range.end, muted_style));
 6346            }
 6347            prev_end = cmp::max(prev_end, range.end);
 6348
 6349            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6350                runs.push((prev_end..label.text.len(), fade_out));
 6351            }
 6352
 6353            runs
 6354        })
 6355}
 6356
 6357#[cfg(test)]
 6358mod tests {
 6359    use crate::test::{
 6360        assert_text_with_selections, build_editor, select_ranges, EditorLspTestContext,
 6361        EditorTestContext,
 6362    };
 6363
 6364    use super::*;
 6365    use futures::StreamExt;
 6366    use gpui::{
 6367        geometry::rect::RectF,
 6368        platform::{WindowBounds, WindowOptions},
 6369    };
 6370    use indoc::indoc;
 6371    use language::{FakeLspAdapter, LanguageConfig};
 6372    use project::FakeFs;
 6373    use settings::EditorSettings;
 6374    use std::{cell::RefCell, rc::Rc, time::Instant};
 6375    use text::Point;
 6376    use unindent::Unindent;
 6377    use util::{
 6378        assert_set_eq,
 6379        test::{
 6380            marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker,
 6381        },
 6382    };
 6383    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6384
 6385    #[gpui::test]
 6386    fn test_edit_events(cx: &mut MutableAppContext) {
 6387        cx.set_global(Settings::test(cx));
 6388        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6389
 6390        let events = Rc::new(RefCell::new(Vec::new()));
 6391        let (_, editor1) = cx.add_window(Default::default(), {
 6392            let events = events.clone();
 6393            |cx| {
 6394                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6395                    if matches!(
 6396                        event,
 6397                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6398                    ) {
 6399                        events.borrow_mut().push(("editor1", *event));
 6400                    }
 6401                })
 6402                .detach();
 6403                Editor::for_buffer(buffer.clone(), None, cx)
 6404            }
 6405        });
 6406        let (_, editor2) = cx.add_window(Default::default(), {
 6407            let events = events.clone();
 6408            |cx| {
 6409                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6410                    if matches!(
 6411                        event,
 6412                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6413                    ) {
 6414                        events.borrow_mut().push(("editor2", *event));
 6415                    }
 6416                })
 6417                .detach();
 6418                Editor::for_buffer(buffer.clone(), None, cx)
 6419            }
 6420        });
 6421        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6422
 6423        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6424        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6425        assert_eq!(
 6426            mem::take(&mut *events.borrow_mut()),
 6427            [
 6428                ("editor1", Event::Edited),
 6429                ("editor1", Event::BufferEdited),
 6430                ("editor2", Event::BufferEdited),
 6431                ("editor1", Event::DirtyChanged),
 6432                ("editor2", Event::DirtyChanged)
 6433            ]
 6434        );
 6435
 6436        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6437        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6438        assert_eq!(
 6439            mem::take(&mut *events.borrow_mut()),
 6440            [
 6441                ("editor2", Event::Edited),
 6442                ("editor1", Event::BufferEdited),
 6443                ("editor2", Event::BufferEdited),
 6444            ]
 6445        );
 6446
 6447        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6448        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6449        assert_eq!(
 6450            mem::take(&mut *events.borrow_mut()),
 6451            [
 6452                ("editor1", Event::Edited),
 6453                ("editor1", Event::BufferEdited),
 6454                ("editor2", Event::BufferEdited),
 6455                ("editor1", Event::DirtyChanged),
 6456                ("editor2", Event::DirtyChanged),
 6457            ]
 6458        );
 6459
 6460        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6461        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6462        assert_eq!(
 6463            mem::take(&mut *events.borrow_mut()),
 6464            [
 6465                ("editor1", Event::Edited),
 6466                ("editor1", Event::BufferEdited),
 6467                ("editor2", Event::BufferEdited),
 6468                ("editor1", Event::DirtyChanged),
 6469                ("editor2", Event::DirtyChanged),
 6470            ]
 6471        );
 6472
 6473        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6474        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6475        assert_eq!(
 6476            mem::take(&mut *events.borrow_mut()),
 6477            [
 6478                ("editor2", Event::Edited),
 6479                ("editor1", Event::BufferEdited),
 6480                ("editor2", Event::BufferEdited),
 6481                ("editor1", Event::DirtyChanged),
 6482                ("editor2", Event::DirtyChanged),
 6483            ]
 6484        );
 6485
 6486        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6487        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6488        assert_eq!(
 6489            mem::take(&mut *events.borrow_mut()),
 6490            [
 6491                ("editor2", Event::Edited),
 6492                ("editor1", Event::BufferEdited),
 6493                ("editor2", Event::BufferEdited),
 6494                ("editor1", Event::DirtyChanged),
 6495                ("editor2", Event::DirtyChanged),
 6496            ]
 6497        );
 6498
 6499        // No event is emitted when the mutation is a no-op.
 6500        editor2.update(cx, |editor, cx| {
 6501            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6502
 6503            editor.backspace(&Backspace, cx);
 6504        });
 6505        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6506    }
 6507
 6508    #[gpui::test]
 6509    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6510        cx.set_global(Settings::test(cx));
 6511        let mut now = Instant::now();
 6512        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6513        let group_interval = buffer.read(cx).transaction_group_interval();
 6514        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6515        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6516
 6517        editor.update(cx, |editor, cx| {
 6518            editor.start_transaction_at(now, cx);
 6519            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6520
 6521            editor.insert("cd", cx);
 6522            editor.end_transaction_at(now, cx);
 6523            assert_eq!(editor.text(cx), "12cd56");
 6524            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6525
 6526            editor.start_transaction_at(now, cx);
 6527            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6528            editor.insert("e", cx);
 6529            editor.end_transaction_at(now, cx);
 6530            assert_eq!(editor.text(cx), "12cde6");
 6531            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6532
 6533            now += group_interval + Duration::from_millis(1);
 6534            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6535
 6536            // Simulate an edit in another editor
 6537            buffer.update(cx, |buffer, cx| {
 6538                buffer.start_transaction_at(now, cx);
 6539                buffer.edit([(0..1, "a")], cx);
 6540                buffer.edit([(1..1, "b")], cx);
 6541                buffer.end_transaction_at(now, cx);
 6542            });
 6543
 6544            assert_eq!(editor.text(cx), "ab2cde6");
 6545            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6546
 6547            // Last transaction happened past the group interval in a different editor.
 6548            // Undo it individually and don't restore selections.
 6549            editor.undo(&Undo, cx);
 6550            assert_eq!(editor.text(cx), "12cde6");
 6551            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6552
 6553            // First two transactions happened within the group interval in this editor.
 6554            // Undo them together and restore selections.
 6555            editor.undo(&Undo, cx);
 6556            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6557            assert_eq!(editor.text(cx), "123456");
 6558            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6559
 6560            // Redo the first two transactions together.
 6561            editor.redo(&Redo, cx);
 6562            assert_eq!(editor.text(cx), "12cde6");
 6563            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6564
 6565            // Redo the last transaction on its own.
 6566            editor.redo(&Redo, cx);
 6567            assert_eq!(editor.text(cx), "ab2cde6");
 6568            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6569
 6570            // Test empty transactions.
 6571            editor.start_transaction_at(now, cx);
 6572            editor.end_transaction_at(now, cx);
 6573            editor.undo(&Undo, cx);
 6574            assert_eq!(editor.text(cx), "12cde6");
 6575        });
 6576    }
 6577
 6578    #[gpui::test]
 6579    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6580        cx.set_global(Settings::test(cx));
 6581
 6582        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6583        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6584        editor.update(cx, |view, cx| {
 6585            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6586        });
 6587        assert_eq!(
 6588            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6589            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6590        );
 6591
 6592        editor.update(cx, |view, cx| {
 6593            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6594        });
 6595
 6596        assert_eq!(
 6597            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6598            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6599        );
 6600
 6601        editor.update(cx, |view, cx| {
 6602            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6603        });
 6604
 6605        assert_eq!(
 6606            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6607            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6608        );
 6609
 6610        editor.update(cx, |view, cx| {
 6611            view.end_selection(cx);
 6612            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6613        });
 6614
 6615        assert_eq!(
 6616            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6617            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6618        );
 6619
 6620        editor.update(cx, |view, cx| {
 6621            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6622            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6623        });
 6624
 6625        assert_eq!(
 6626            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6627            [
 6628                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6629                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6630            ]
 6631        );
 6632
 6633        editor.update(cx, |view, cx| {
 6634            view.end_selection(cx);
 6635        });
 6636
 6637        assert_eq!(
 6638            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6639            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6640        );
 6641    }
 6642
 6643    #[gpui::test]
 6644    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6645        cx.set_global(Settings::test(cx));
 6646        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6647        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6648
 6649        view.update(cx, |view, cx| {
 6650            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6651            assert_eq!(
 6652                view.selections.display_ranges(cx),
 6653                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6654            );
 6655        });
 6656
 6657        view.update(cx, |view, cx| {
 6658            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6659            assert_eq!(
 6660                view.selections.display_ranges(cx),
 6661                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6662            );
 6663        });
 6664
 6665        view.update(cx, |view, cx| {
 6666            view.cancel(&Cancel, cx);
 6667            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6668            assert_eq!(
 6669                view.selections.display_ranges(cx),
 6670                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6671            );
 6672        });
 6673    }
 6674
 6675    #[gpui::test]
 6676    fn test_clone(cx: &mut gpui::MutableAppContext) {
 6677        let (text, selection_ranges) = marked_text_ranges(indoc! {"
 6678            one
 6679            two
 6680            three[]
 6681            four
 6682            five[]
 6683        "});
 6684        cx.set_global(Settings::test(cx));
 6685        let buffer = MultiBuffer::build_simple(&text, cx);
 6686
 6687        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6688
 6689        editor.update(cx, |editor, cx| {
 6690            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 6691            editor.fold_ranges(
 6692                [
 6693                    Point::new(1, 0)..Point::new(2, 0),
 6694                    Point::new(3, 0)..Point::new(4, 0),
 6695                ],
 6696                cx,
 6697            );
 6698        });
 6699
 6700        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 6701            cx.add_window(Default::default(), |cx| editor.clone(cx))
 6702        });
 6703
 6704        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 6705        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 6706
 6707        assert_eq!(
 6708            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 6709            editor.update(cx, |e, cx| e.display_text(cx))
 6710        );
 6711        assert_eq!(
 6712            cloned_snapshot
 6713                .folds_in_range(0..text.len())
 6714                .collect::<Vec<_>>(),
 6715            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 6716        );
 6717        assert_set_eq!(
 6718            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 6719            editor.read(cx).selections.ranges(cx)
 6720        );
 6721        assert_set_eq!(
 6722            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 6723            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 6724        );
 6725    }
 6726
 6727    #[gpui::test]
 6728    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6729        cx.set_global(Settings::test(cx));
 6730        use workspace::Item;
 6731        let pane = cx.add_view(Default::default(), |cx| Pane::new(cx));
 6732        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6733
 6734        cx.add_window(Default::default(), |cx| {
 6735            let mut editor = build_editor(buffer.clone(), cx);
 6736            let handle = cx.handle();
 6737            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 6738
 6739            fn pop_history(
 6740                editor: &mut Editor,
 6741                cx: &mut MutableAppContext,
 6742            ) -> Option<NavigationEntry> {
 6743                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 6744            }
 6745
 6746            // Move the cursor a small distance.
 6747            // Nothing is added to the navigation history.
 6748            editor.change_selections(None, cx, |s| {
 6749                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 6750            });
 6751            editor.change_selections(None, cx, |s| {
 6752                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 6753            });
 6754            assert!(pop_history(&mut editor, cx).is_none());
 6755
 6756            // Move the cursor a large distance.
 6757            // The history can jump back to the previous position.
 6758            editor.change_selections(None, cx, |s| {
 6759                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 6760            });
 6761            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6762            editor.navigate(nav_entry.data.unwrap(), cx);
 6763            assert_eq!(nav_entry.item.id(), cx.view_id());
 6764            assert_eq!(
 6765                editor.selections.display_ranges(cx),
 6766                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6767            );
 6768            assert!(pop_history(&mut editor, cx).is_none());
 6769
 6770            // Move the cursor a small distance via the mouse.
 6771            // Nothing is added to the navigation history.
 6772            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6773            editor.end_selection(cx);
 6774            assert_eq!(
 6775                editor.selections.display_ranges(cx),
 6776                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6777            );
 6778            assert!(pop_history(&mut editor, cx).is_none());
 6779
 6780            // Move the cursor a large distance via the mouse.
 6781            // The history can jump back to the previous position.
 6782            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6783            editor.end_selection(cx);
 6784            assert_eq!(
 6785                editor.selections.display_ranges(cx),
 6786                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6787            );
 6788            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6789            editor.navigate(nav_entry.data.unwrap(), cx);
 6790            assert_eq!(nav_entry.item.id(), cx.view_id());
 6791            assert_eq!(
 6792                editor.selections.display_ranges(cx),
 6793                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6794            );
 6795            assert!(pop_history(&mut editor, cx).is_none());
 6796
 6797            // Set scroll position to check later
 6798            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6799            let original_scroll_position = editor.scroll_position;
 6800            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6801
 6802            // Jump to the end of the document and adjust scroll
 6803            editor.move_to_end(&MoveToEnd, cx);
 6804            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6805            assert_ne!(editor.scroll_position, original_scroll_position);
 6806            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6807
 6808            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6809            editor.navigate(nav_entry.data.unwrap(), cx);
 6810            assert_eq!(editor.scroll_position, original_scroll_position);
 6811            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6812
 6813            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6814            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6815            invalid_anchor.text_anchor.buffer_id = Some(999);
 6816            let invalid_point = Point::new(9999, 0);
 6817            editor.navigate(
 6818                Box::new(NavigationData {
 6819                    cursor_anchor: invalid_anchor.clone(),
 6820                    cursor_position: invalid_point,
 6821                    scroll_top_anchor: invalid_anchor.clone(),
 6822                    scroll_top_row: invalid_point.row,
 6823                    scroll_position: Default::default(),
 6824                }),
 6825                cx,
 6826            );
 6827            assert_eq!(
 6828                editor.selections.display_ranges(cx),
 6829                &[editor.max_point(cx)..editor.max_point(cx)]
 6830            );
 6831            assert_eq!(
 6832                editor.scroll_position(cx),
 6833                vec2f(0., editor.max_point(cx).row() as f32)
 6834            );
 6835
 6836            editor
 6837        });
 6838    }
 6839
 6840    #[gpui::test]
 6841    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6842        cx.set_global(Settings::test(cx));
 6843        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6844        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6845
 6846        view.update(cx, |view, cx| {
 6847            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6848            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6849            view.end_selection(cx);
 6850
 6851            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6852            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6853            view.end_selection(cx);
 6854            assert_eq!(
 6855                view.selections.display_ranges(cx),
 6856                [
 6857                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6858                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6859                ]
 6860            );
 6861        });
 6862
 6863        view.update(cx, |view, cx| {
 6864            view.cancel(&Cancel, cx);
 6865            assert_eq!(
 6866                view.selections.display_ranges(cx),
 6867                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6868            );
 6869        });
 6870
 6871        view.update(cx, |view, cx| {
 6872            view.cancel(&Cancel, cx);
 6873            assert_eq!(
 6874                view.selections.display_ranges(cx),
 6875                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6876            );
 6877        });
 6878    }
 6879
 6880    #[gpui::test]
 6881    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6882        cx.set_global(Settings::test(cx));
 6883        let buffer = MultiBuffer::build_simple(
 6884            &"
 6885                impl Foo {
 6886                    // Hello!
 6887
 6888                    fn a() {
 6889                        1
 6890                    }
 6891
 6892                    fn b() {
 6893                        2
 6894                    }
 6895
 6896                    fn c() {
 6897                        3
 6898                    }
 6899                }
 6900            "
 6901            .unindent(),
 6902            cx,
 6903        );
 6904        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6905
 6906        view.update(cx, |view, cx| {
 6907            view.change_selections(None, cx, |s| {
 6908                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 6909            });
 6910            view.fold(&Fold, cx);
 6911            assert_eq!(
 6912                view.display_text(cx),
 6913                "
 6914                    impl Foo {
 6915                        // Hello!
 6916
 6917                        fn a() {
 6918                            1
 6919                        }
 6920
 6921                        fn b() {…
 6922                        }
 6923
 6924                        fn c() {…
 6925                        }
 6926                    }
 6927                "
 6928                .unindent(),
 6929            );
 6930
 6931            view.fold(&Fold, cx);
 6932            assert_eq!(
 6933                view.display_text(cx),
 6934                "
 6935                    impl Foo {…
 6936                    }
 6937                "
 6938                .unindent(),
 6939            );
 6940
 6941            view.unfold_lines(&UnfoldLines, cx);
 6942            assert_eq!(
 6943                view.display_text(cx),
 6944                "
 6945                    impl Foo {
 6946                        // Hello!
 6947
 6948                        fn a() {
 6949                            1
 6950                        }
 6951
 6952                        fn b() {…
 6953                        }
 6954
 6955                        fn c() {…
 6956                        }
 6957                    }
 6958                "
 6959                .unindent(),
 6960            );
 6961
 6962            view.unfold_lines(&UnfoldLines, cx);
 6963            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6964        });
 6965    }
 6966
 6967    #[gpui::test]
 6968    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6969        cx.set_global(Settings::test(cx));
 6970        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6971        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6972
 6973        buffer.update(cx, |buffer, cx| {
 6974            buffer.edit(
 6975                vec![
 6976                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 6977                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 6978                ],
 6979                cx,
 6980            );
 6981        });
 6982
 6983        view.update(cx, |view, cx| {
 6984            assert_eq!(
 6985                view.selections.display_ranges(cx),
 6986                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6987            );
 6988
 6989            view.move_down(&MoveDown, cx);
 6990            assert_eq!(
 6991                view.selections.display_ranges(cx),
 6992                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6993            );
 6994
 6995            view.move_right(&MoveRight, cx);
 6996            assert_eq!(
 6997                view.selections.display_ranges(cx),
 6998                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6999            );
 7000
 7001            view.move_left(&MoveLeft, cx);
 7002            assert_eq!(
 7003                view.selections.display_ranges(cx),
 7004                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7005            );
 7006
 7007            view.move_up(&MoveUp, cx);
 7008            assert_eq!(
 7009                view.selections.display_ranges(cx),
 7010                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7011            );
 7012
 7013            view.move_to_end(&MoveToEnd, cx);
 7014            assert_eq!(
 7015                view.selections.display_ranges(cx),
 7016                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7017            );
 7018
 7019            view.move_to_beginning(&MoveToBeginning, cx);
 7020            assert_eq!(
 7021                view.selections.display_ranges(cx),
 7022                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7023            );
 7024
 7025            view.change_selections(None, cx, |s| {
 7026                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 7027            });
 7028            view.select_to_beginning(&SelectToBeginning, cx);
 7029            assert_eq!(
 7030                view.selections.display_ranges(cx),
 7031                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7032            );
 7033
 7034            view.select_to_end(&SelectToEnd, cx);
 7035            assert_eq!(
 7036                view.selections.display_ranges(cx),
 7037                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7038            );
 7039        });
 7040    }
 7041
 7042    #[gpui::test]
 7043    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7044        cx.set_global(Settings::test(cx));
 7045        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7046        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7047
 7048        assert_eq!('ⓐ'.len_utf8(), 3);
 7049        assert_eq!('α'.len_utf8(), 2);
 7050
 7051        view.update(cx, |view, cx| {
 7052            view.fold_ranges(
 7053                vec![
 7054                    Point::new(0, 6)..Point::new(0, 12),
 7055                    Point::new(1, 2)..Point::new(1, 4),
 7056                    Point::new(2, 4)..Point::new(2, 8),
 7057                ],
 7058                cx,
 7059            );
 7060            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7061
 7062            view.move_right(&MoveRight, cx);
 7063            assert_eq!(
 7064                view.selections.display_ranges(cx),
 7065                &[empty_range(0, "".len())]
 7066            );
 7067            view.move_right(&MoveRight, cx);
 7068            assert_eq!(
 7069                view.selections.display_ranges(cx),
 7070                &[empty_range(0, "ⓐⓑ".len())]
 7071            );
 7072            view.move_right(&MoveRight, cx);
 7073            assert_eq!(
 7074                view.selections.display_ranges(cx),
 7075                &[empty_range(0, "ⓐⓑ…".len())]
 7076            );
 7077
 7078            view.move_down(&MoveDown, cx);
 7079            assert_eq!(
 7080                view.selections.display_ranges(cx),
 7081                &[empty_range(1, "ab…".len())]
 7082            );
 7083            view.move_left(&MoveLeft, cx);
 7084            assert_eq!(
 7085                view.selections.display_ranges(cx),
 7086                &[empty_range(1, "ab".len())]
 7087            );
 7088            view.move_left(&MoveLeft, cx);
 7089            assert_eq!(
 7090                view.selections.display_ranges(cx),
 7091                &[empty_range(1, "a".len())]
 7092            );
 7093
 7094            view.move_down(&MoveDown, cx);
 7095            assert_eq!(
 7096                view.selections.display_ranges(cx),
 7097                &[empty_range(2, "α".len())]
 7098            );
 7099            view.move_right(&MoveRight, cx);
 7100            assert_eq!(
 7101                view.selections.display_ranges(cx),
 7102                &[empty_range(2, "αβ".len())]
 7103            );
 7104            view.move_right(&MoveRight, cx);
 7105            assert_eq!(
 7106                view.selections.display_ranges(cx),
 7107                &[empty_range(2, "αβ…".len())]
 7108            );
 7109            view.move_right(&MoveRight, cx);
 7110            assert_eq!(
 7111                view.selections.display_ranges(cx),
 7112                &[empty_range(2, "αβ…ε".len())]
 7113            );
 7114
 7115            view.move_up(&MoveUp, cx);
 7116            assert_eq!(
 7117                view.selections.display_ranges(cx),
 7118                &[empty_range(1, "ab…e".len())]
 7119            );
 7120            view.move_up(&MoveUp, cx);
 7121            assert_eq!(
 7122                view.selections.display_ranges(cx),
 7123                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7124            );
 7125            view.move_left(&MoveLeft, cx);
 7126            assert_eq!(
 7127                view.selections.display_ranges(cx),
 7128                &[empty_range(0, "ⓐⓑ…".len())]
 7129            );
 7130            view.move_left(&MoveLeft, cx);
 7131            assert_eq!(
 7132                view.selections.display_ranges(cx),
 7133                &[empty_range(0, "ⓐⓑ".len())]
 7134            );
 7135            view.move_left(&MoveLeft, cx);
 7136            assert_eq!(
 7137                view.selections.display_ranges(cx),
 7138                &[empty_range(0, "".len())]
 7139            );
 7140        });
 7141    }
 7142
 7143    #[gpui::test]
 7144    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7145        cx.set_global(Settings::test(cx));
 7146        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7147        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7148        view.update(cx, |view, cx| {
 7149            view.change_selections(None, cx, |s| {
 7150                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7151            });
 7152            view.move_down(&MoveDown, cx);
 7153            assert_eq!(
 7154                view.selections.display_ranges(cx),
 7155                &[empty_range(1, "abcd".len())]
 7156            );
 7157
 7158            view.move_down(&MoveDown, cx);
 7159            assert_eq!(
 7160                view.selections.display_ranges(cx),
 7161                &[empty_range(2, "αβγ".len())]
 7162            );
 7163
 7164            view.move_down(&MoveDown, cx);
 7165            assert_eq!(
 7166                view.selections.display_ranges(cx),
 7167                &[empty_range(3, "abcd".len())]
 7168            );
 7169
 7170            view.move_down(&MoveDown, cx);
 7171            assert_eq!(
 7172                view.selections.display_ranges(cx),
 7173                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7174            );
 7175
 7176            view.move_up(&MoveUp, cx);
 7177            assert_eq!(
 7178                view.selections.display_ranges(cx),
 7179                &[empty_range(3, "abcd".len())]
 7180            );
 7181
 7182            view.move_up(&MoveUp, cx);
 7183            assert_eq!(
 7184                view.selections.display_ranges(cx),
 7185                &[empty_range(2, "αβγ".len())]
 7186            );
 7187        });
 7188    }
 7189
 7190    #[gpui::test]
 7191    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7192        cx.set_global(Settings::test(cx));
 7193        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7194        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7195        view.update(cx, |view, cx| {
 7196            view.change_selections(None, cx, |s| {
 7197                s.select_display_ranges([
 7198                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7199                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7200                ]);
 7201            });
 7202        });
 7203
 7204        view.update(cx, |view, cx| {
 7205            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7206            assert_eq!(
 7207                view.selections.display_ranges(cx),
 7208                &[
 7209                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7210                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7211                ]
 7212            );
 7213        });
 7214
 7215        view.update(cx, |view, cx| {
 7216            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7217            assert_eq!(
 7218                view.selections.display_ranges(cx),
 7219                &[
 7220                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7221                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7222                ]
 7223            );
 7224        });
 7225
 7226        view.update(cx, |view, cx| {
 7227            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7228            assert_eq!(
 7229                view.selections.display_ranges(cx),
 7230                &[
 7231                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7232                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7233                ]
 7234            );
 7235        });
 7236
 7237        view.update(cx, |view, cx| {
 7238            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7239            assert_eq!(
 7240                view.selections.display_ranges(cx),
 7241                &[
 7242                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7243                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7244                ]
 7245            );
 7246        });
 7247
 7248        // Moving to the end of line again is a no-op.
 7249        view.update(cx, |view, cx| {
 7250            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7251            assert_eq!(
 7252                view.selections.display_ranges(cx),
 7253                &[
 7254                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7255                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7256                ]
 7257            );
 7258        });
 7259
 7260        view.update(cx, |view, cx| {
 7261            view.move_left(&MoveLeft, cx);
 7262            view.select_to_beginning_of_line(
 7263                &SelectToBeginningOfLine {
 7264                    stop_at_soft_wraps: true,
 7265                },
 7266                cx,
 7267            );
 7268            assert_eq!(
 7269                view.selections.display_ranges(cx),
 7270                &[
 7271                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7272                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7273                ]
 7274            );
 7275        });
 7276
 7277        view.update(cx, |view, cx| {
 7278            view.select_to_beginning_of_line(
 7279                &SelectToBeginningOfLine {
 7280                    stop_at_soft_wraps: true,
 7281                },
 7282                cx,
 7283            );
 7284            assert_eq!(
 7285                view.selections.display_ranges(cx),
 7286                &[
 7287                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7288                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7289                ]
 7290            );
 7291        });
 7292
 7293        view.update(cx, |view, cx| {
 7294            view.select_to_beginning_of_line(
 7295                &SelectToBeginningOfLine {
 7296                    stop_at_soft_wraps: true,
 7297                },
 7298                cx,
 7299            );
 7300            assert_eq!(
 7301                view.selections.display_ranges(cx),
 7302                &[
 7303                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7304                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7305                ]
 7306            );
 7307        });
 7308
 7309        view.update(cx, |view, cx| {
 7310            view.select_to_end_of_line(
 7311                &SelectToEndOfLine {
 7312                    stop_at_soft_wraps: true,
 7313                },
 7314                cx,
 7315            );
 7316            assert_eq!(
 7317                view.selections.display_ranges(cx),
 7318                &[
 7319                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7320                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7321                ]
 7322            );
 7323        });
 7324
 7325        view.update(cx, |view, cx| {
 7326            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7327            assert_eq!(view.display_text(cx), "ab\n  de");
 7328            assert_eq!(
 7329                view.selections.display_ranges(cx),
 7330                &[
 7331                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7332                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7333                ]
 7334            );
 7335        });
 7336
 7337        view.update(cx, |view, cx| {
 7338            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7339            assert_eq!(view.display_text(cx), "\n");
 7340            assert_eq!(
 7341                view.selections.display_ranges(cx),
 7342                &[
 7343                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7344                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7345                ]
 7346            );
 7347        });
 7348    }
 7349
 7350    #[gpui::test]
 7351    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7352        cx.set_global(Settings::test(cx));
 7353        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7354        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7355        view.update(cx, |view, cx| {
 7356            view.change_selections(None, cx, |s| {
 7357                s.select_display_ranges([
 7358                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7359                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7360                ])
 7361            });
 7362
 7363            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7364            assert_selection_ranges(
 7365                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7366                vec![('<', '>'), ('[', ']')],
 7367                view,
 7368                cx,
 7369            );
 7370
 7371            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7372            assert_selection_ranges(
 7373                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7374                vec![('<', '>'), ('[', ']')],
 7375                view,
 7376                cx,
 7377            );
 7378
 7379            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7380            assert_selection_ranges(
 7381                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7382                vec![('<', '>'), ('[', ']')],
 7383                view,
 7384                cx,
 7385            );
 7386
 7387            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7388            assert_selection_ranges(
 7389                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7390                vec![('<', '>'), ('[', ']')],
 7391                view,
 7392                cx,
 7393            );
 7394
 7395            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7396            assert_selection_ranges(
 7397                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7398                vec![('<', '>'), ('[', ']')],
 7399                view,
 7400                cx,
 7401            );
 7402
 7403            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7404            assert_selection_ranges(
 7405                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7406                vec![('<', '>'), ('[', ']')],
 7407                view,
 7408                cx,
 7409            );
 7410
 7411            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7412            assert_selection_ranges(
 7413                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7414                vec![('<', '>'), ('[', ']')],
 7415                view,
 7416                cx,
 7417            );
 7418
 7419            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7420            assert_selection_ranges(
 7421                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7422                vec![('<', '>'), ('[', ']')],
 7423                view,
 7424                cx,
 7425            );
 7426
 7427            view.move_right(&MoveRight, cx);
 7428            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7429            assert_selection_ranges(
 7430                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7431                vec![('<', '>'), ('[', ']')],
 7432                view,
 7433                cx,
 7434            );
 7435
 7436            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7437            assert_selection_ranges(
 7438                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7439                vec![('<', '>'), ('[', ']')],
 7440                view,
 7441                cx,
 7442            );
 7443
 7444            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7445            assert_selection_ranges(
 7446                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7447                vec![('<', '>'), ('[', ']')],
 7448                view,
 7449                cx,
 7450            );
 7451        });
 7452    }
 7453
 7454    #[gpui::test]
 7455    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7456        cx.set_global(Settings::test(cx));
 7457        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7458        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7459
 7460        view.update(cx, |view, cx| {
 7461            view.set_wrap_width(Some(140.), cx);
 7462            assert_eq!(
 7463                view.display_text(cx),
 7464                "use one::{\n    two::three::\n    four::five\n};"
 7465            );
 7466
 7467            view.change_selections(None, cx, |s| {
 7468                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7469            });
 7470
 7471            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7472            assert_eq!(
 7473                view.selections.display_ranges(cx),
 7474                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7475            );
 7476
 7477            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7478            assert_eq!(
 7479                view.selections.display_ranges(cx),
 7480                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7481            );
 7482
 7483            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7484            assert_eq!(
 7485                view.selections.display_ranges(cx),
 7486                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7487            );
 7488
 7489            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7490            assert_eq!(
 7491                view.selections.display_ranges(cx),
 7492                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7493            );
 7494
 7495            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7496            assert_eq!(
 7497                view.selections.display_ranges(cx),
 7498                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7499            );
 7500
 7501            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7502            assert_eq!(
 7503                view.selections.display_ranges(cx),
 7504                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7505            );
 7506        });
 7507    }
 7508
 7509    #[gpui::test]
 7510    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7511        cx.set_global(Settings::test(cx));
 7512        let (text, ranges) = marked_text_ranges("one [two three] four");
 7513        let buffer = MultiBuffer::build_simple(&text, cx);
 7514
 7515        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7516
 7517        editor.update(cx, |editor, cx| {
 7518            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
 7519            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7520            assert_eq!(editor.text(cx), " four");
 7521        });
 7522    }
 7523
 7524    #[gpui::test]
 7525    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7526        cx.set_global(Settings::test(cx));
 7527        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7528        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7529
 7530        view.update(cx, |view, cx| {
 7531            view.change_selections(None, cx, |s| {
 7532                s.select_display_ranges([
 7533                    // an empty selection - the preceding word fragment is deleted
 7534                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7535                    // characters selected - they are deleted
 7536                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7537                ])
 7538            });
 7539            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7540        });
 7541
 7542        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7543
 7544        view.update(cx, |view, cx| {
 7545            view.change_selections(None, cx, |s| {
 7546                s.select_display_ranges([
 7547                    // an empty selection - the following word fragment is deleted
 7548                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7549                    // characters selected - they are deleted
 7550                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7551                ])
 7552            });
 7553            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7554        });
 7555
 7556        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7557    }
 7558
 7559    #[gpui::test]
 7560    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7561        cx.set_global(Settings::test(cx));
 7562        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7563        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7564
 7565        view.update(cx, |view, cx| {
 7566            view.change_selections(None, cx, |s| {
 7567                s.select_display_ranges([
 7568                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7569                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7570                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7571                ])
 7572            });
 7573
 7574            view.newline(&Newline, cx);
 7575            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7576        });
 7577    }
 7578
 7579    #[gpui::test]
 7580    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7581        cx.set_global(Settings::test(cx));
 7582        let buffer = MultiBuffer::build_simple(
 7583            "
 7584                a
 7585                b(
 7586                    X
 7587                )
 7588                c(
 7589                    X
 7590                )
 7591            "
 7592            .unindent()
 7593            .as_str(),
 7594            cx,
 7595        );
 7596
 7597        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7598            let mut editor = build_editor(buffer.clone(), cx);
 7599            editor.change_selections(None, cx, |s| {
 7600                s.select_ranges([
 7601                    Point::new(2, 4)..Point::new(2, 5),
 7602                    Point::new(5, 4)..Point::new(5, 5),
 7603                ])
 7604            });
 7605            editor
 7606        });
 7607
 7608        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7609        buffer.update(cx, |buffer, cx| {
 7610            buffer.edit(
 7611                [
 7612                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7613                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7614                ],
 7615                cx,
 7616            );
 7617            assert_eq!(
 7618                buffer.read(cx).text(),
 7619                "
 7620                    a
 7621                    b()
 7622                    c()
 7623                "
 7624                .unindent()
 7625            );
 7626        });
 7627
 7628        editor.update(cx, |editor, cx| {
 7629            assert_eq!(
 7630                editor.selections.ranges(cx),
 7631                &[
 7632                    Point::new(1, 2)..Point::new(1, 2),
 7633                    Point::new(2, 2)..Point::new(2, 2),
 7634                ],
 7635            );
 7636
 7637            editor.newline(&Newline, cx);
 7638            assert_eq!(
 7639                editor.text(cx),
 7640                "
 7641                    a
 7642                    b(
 7643                    )
 7644                    c(
 7645                    )
 7646                "
 7647                .unindent()
 7648            );
 7649
 7650            // The selections are moved after the inserted newlines
 7651            assert_eq!(
 7652                editor.selections.ranges(cx),
 7653                &[
 7654                    Point::new(2, 0)..Point::new(2, 0),
 7655                    Point::new(4, 0)..Point::new(4, 0),
 7656                ],
 7657            );
 7658        });
 7659    }
 7660
 7661    #[gpui::test]
 7662    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7663        cx.set_global(Settings::test(cx));
 7664        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7665        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7666            let mut editor = build_editor(buffer.clone(), cx);
 7667            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 7668            editor
 7669        });
 7670
 7671        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7672        buffer.update(cx, |buffer, cx| {
 7673            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7674            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7675        });
 7676
 7677        editor.update(cx, |editor, cx| {
 7678            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 7679
 7680            editor.insert("Z", cx);
 7681            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7682
 7683            // The selections are moved after the inserted characters
 7684            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 7685        });
 7686    }
 7687
 7688    #[gpui::test]
 7689    async fn test_tab(cx: &mut gpui::TestAppContext) {
 7690        let mut cx = EditorTestContext::new(cx).await;
 7691        cx.update(|cx| {
 7692            cx.update_global::<Settings, _, _>(|settings, _| {
 7693                settings.editor_overrides.tab_size = Some(NonZeroU32::new(3).unwrap());
 7694            });
 7695        });
 7696        cx.set_state(indoc! {"
 7697            |ab|c
 7698            |🏀|🏀|efg
 7699            d|
 7700        "});
 7701        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7702        cx.assert_editor_state(indoc! {"
 7703              |ab |c
 7704              |🏀  |🏀  |efg
 7705           d  |
 7706        "});
 7707    }
 7708
 7709    #[gpui::test]
 7710    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 7711        let mut cx = EditorTestContext::new(cx).await;
 7712
 7713        cx.set_state(indoc! {"
 7714              [one} [two}
 7715            three
 7716             four"});
 7717        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7718        cx.assert_editor_state(indoc! {"
 7719                [one} [two}
 7720            three
 7721             four"});
 7722
 7723        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7724        cx.assert_editor_state(indoc! {"
 7725            [one} [two}
 7726            three
 7727             four"});
 7728
 7729        // select across line ending
 7730        cx.set_state(indoc! {"
 7731            one two
 7732            t[hree
 7733            } four"});
 7734        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7735        cx.assert_editor_state(indoc! {"
 7736            one two
 7737                t[hree
 7738            } four"});
 7739
 7740        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7741        cx.assert_editor_state(indoc! {"
 7742            one two
 7743            t[hree
 7744            } four"});
 7745
 7746        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7747        cx.set_state(indoc! {"
 7748            one two
 7749            |three
 7750                four"});
 7751        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7752        cx.assert_editor_state(indoc! {"
 7753            one two
 7754                |three
 7755                four"});
 7756
 7757        cx.set_state(indoc! {"
 7758            one two
 7759            |    three
 7760             four"});
 7761        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7762        cx.assert_editor_state(indoc! {"
 7763            one two
 7764            |three
 7765             four"});
 7766    }
 7767
 7768    #[gpui::test]
 7769    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 7770        let mut cx = EditorTestContext::new(cx).await;
 7771        cx.update(|cx| {
 7772            cx.update_global::<Settings, _, _>(|settings, _| {
 7773                settings.editor_overrides.hard_tabs = Some(true);
 7774            });
 7775        });
 7776
 7777        // select two ranges on one line
 7778        cx.set_state(indoc! {"
 7779            [one} [two}
 7780            three
 7781            four"});
 7782        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7783        cx.assert_editor_state(indoc! {"
 7784            \t[one} [two}
 7785            three
 7786            four"});
 7787        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7788        cx.assert_editor_state(indoc! {"
 7789            \t\t[one} [two}
 7790            three
 7791            four"});
 7792        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7793        cx.assert_editor_state(indoc! {"
 7794            \t[one} [two}
 7795            three
 7796            four"});
 7797        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7798        cx.assert_editor_state(indoc! {"
 7799            [one} [two}
 7800            three
 7801            four"});
 7802
 7803        // select across a line ending
 7804        cx.set_state(indoc! {"
 7805            one two
 7806            t[hree
 7807            }four"});
 7808        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7809        cx.assert_editor_state(indoc! {"
 7810            one two
 7811            \tt[hree
 7812            }four"});
 7813        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7814        cx.assert_editor_state(indoc! {"
 7815            one two
 7816            \t\tt[hree
 7817            }four"});
 7818        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7819        cx.assert_editor_state(indoc! {"
 7820            one two
 7821            \tt[hree
 7822            }four"});
 7823        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7824        cx.assert_editor_state(indoc! {"
 7825            one two
 7826            t[hree
 7827            }four"});
 7828
 7829        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7830        cx.set_state(indoc! {"
 7831            one two
 7832            |three
 7833            four"});
 7834        cx.assert_editor_state(indoc! {"
 7835            one two
 7836            |three
 7837            four"});
 7838        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7839        cx.assert_editor_state(indoc! {"
 7840            one two
 7841            \t|three
 7842            four"});
 7843        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7844        cx.assert_editor_state(indoc! {"
 7845            one two
 7846            |three
 7847            four"});
 7848    }
 7849
 7850    #[gpui::test]
 7851    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7852        cx.set_global(
 7853            Settings::test(cx)
 7854                .with_language_defaults(
 7855                    "TOML",
 7856                    EditorSettings {
 7857                        tab_size: Some(2.try_into().unwrap()),
 7858                        ..Default::default()
 7859                    },
 7860                )
 7861                .with_language_defaults(
 7862                    "Rust",
 7863                    EditorSettings {
 7864                        tab_size: Some(4.try_into().unwrap()),
 7865                        ..Default::default()
 7866                    },
 7867                ),
 7868        );
 7869        let toml_language = Arc::new(Language::new(
 7870            LanguageConfig {
 7871                name: "TOML".into(),
 7872                ..Default::default()
 7873            },
 7874            None,
 7875        ));
 7876        let rust_language = Arc::new(Language::new(
 7877            LanguageConfig {
 7878                name: "Rust".into(),
 7879                ..Default::default()
 7880            },
 7881            None,
 7882        ));
 7883
 7884        let toml_buffer = cx
 7885            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7886        let rust_buffer = cx.add_model(|cx| {
 7887            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7888        });
 7889        let multibuffer = cx.add_model(|cx| {
 7890            let mut multibuffer = MultiBuffer::new(0);
 7891            multibuffer.push_excerpts(
 7892                toml_buffer.clone(),
 7893                [ExcerptRange {
 7894                    context: Point::new(0, 0)..Point::new(2, 0),
 7895                    primary: None,
 7896                }],
 7897                cx,
 7898            );
 7899            multibuffer.push_excerpts(
 7900                rust_buffer.clone(),
 7901                [ExcerptRange {
 7902                    context: Point::new(0, 0)..Point::new(1, 0),
 7903                    primary: None,
 7904                }],
 7905                cx,
 7906            );
 7907            multibuffer
 7908        });
 7909
 7910        cx.add_window(Default::default(), |cx| {
 7911            let mut editor = build_editor(multibuffer, cx);
 7912
 7913            assert_eq!(
 7914                editor.text(cx),
 7915                indoc! {"
 7916                    a = 1
 7917                    b = 2
 7918
 7919                    const c: usize = 3;
 7920                "}
 7921            );
 7922
 7923            select_ranges(
 7924                &mut editor,
 7925                indoc! {"
 7926                    [a] = 1
 7927                    b = 2
 7928
 7929                    [const c:] usize = 3;
 7930                "},
 7931                cx,
 7932            );
 7933
 7934            editor.tab(&Tab, cx);
 7935            assert_text_with_selections(
 7936                &mut editor,
 7937                indoc! {"
 7938                      [a] = 1
 7939                    b = 2
 7940
 7941                        [const c:] usize = 3;
 7942                "},
 7943                cx,
 7944            );
 7945            editor.tab_prev(&TabPrev, cx);
 7946            assert_text_with_selections(
 7947                &mut editor,
 7948                indoc! {"
 7949                    [a] = 1
 7950                    b = 2
 7951
 7952                    [const c:] usize = 3;
 7953                "},
 7954                cx,
 7955            );
 7956
 7957            editor
 7958        });
 7959    }
 7960
 7961    #[gpui::test]
 7962    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 7963        let mut cx = EditorTestContext::new(cx).await;
 7964        // Basic backspace
 7965        cx.set_state(indoc! {"
 7966            on|e two three
 7967            fou[r} five six
 7968            seven {eight nine
 7969            ]ten"});
 7970        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7971        cx.assert_editor_state(indoc! {"
 7972            o|e two three
 7973            fou| five six
 7974            seven |ten"});
 7975
 7976        // Test backspace inside and around indents
 7977        cx.set_state(indoc! {"
 7978            zero
 7979                |one
 7980                    |two
 7981                | | |  three
 7982            |  |  four"});
 7983        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7984        cx.assert_editor_state(indoc! {"
 7985            zero
 7986            |one
 7987                |two
 7988            |  three|  four"});
 7989
 7990        // Test backspace with line_mode set to true
 7991        cx.update_editor(|e, _| e.selections.line_mode = true);
 7992        cx.set_state(indoc! {"
 7993            The |quick |brown
 7994            fox jumps over
 7995            the lazy dog
 7996            |The qu[ick b}rown"});
 7997        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7998        cx.assert_editor_state(indoc! {"
 7999            |fox jumps over
 8000            the lazy dog|"});
 8001    }
 8002
 8003    #[gpui::test]
 8004    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8005        let mut cx = EditorTestContext::new(cx).await;
 8006
 8007        cx.set_state(indoc! {"
 8008            on|e two three
 8009            fou[r} five six
 8010            seven {eight nine
 8011            ]ten"});
 8012        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8013        cx.assert_editor_state(indoc! {"
 8014            on| two three
 8015            fou| five six
 8016            seven |ten"});
 8017
 8018        // Test backspace with line_mode set to true
 8019        cx.update_editor(|e, _| e.selections.line_mode = true);
 8020        cx.set_state(indoc! {"
 8021            The |quick |brown
 8022            fox {jum]ps over
 8023            the lazy dog
 8024            |The qu[ick b}rown"});
 8025        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8026        cx.assert_editor_state("|the lazy dog|");
 8027    }
 8028
 8029    #[gpui::test]
 8030    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8031        cx.set_global(Settings::test(cx));
 8032        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8033        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8034        view.update(cx, |view, cx| {
 8035            view.change_selections(None, cx, |s| {
 8036                s.select_display_ranges([
 8037                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8038                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8039                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8040                ])
 8041            });
 8042            view.delete_line(&DeleteLine, cx);
 8043            assert_eq!(view.display_text(cx), "ghi");
 8044            assert_eq!(
 8045                view.selections.display_ranges(cx),
 8046                vec![
 8047                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8048                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8049                ]
 8050            );
 8051        });
 8052
 8053        cx.set_global(Settings::test(cx));
 8054        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8055        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8056        view.update(cx, |view, cx| {
 8057            view.change_selections(None, cx, |s| {
 8058                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8059            });
 8060            view.delete_line(&DeleteLine, cx);
 8061            assert_eq!(view.display_text(cx), "ghi\n");
 8062            assert_eq!(
 8063                view.selections.display_ranges(cx),
 8064                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8065            );
 8066        });
 8067    }
 8068
 8069    #[gpui::test]
 8070    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8071        cx.set_global(Settings::test(cx));
 8072        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8073        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8074        view.update(cx, |view, cx| {
 8075            view.change_selections(None, cx, |s| {
 8076                s.select_display_ranges([
 8077                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8078                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8079                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8080                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8081                ])
 8082            });
 8083            view.duplicate_line(&DuplicateLine, cx);
 8084            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8085            assert_eq!(
 8086                view.selections.display_ranges(cx),
 8087                vec![
 8088                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8089                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8090                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8091                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8092                ]
 8093            );
 8094        });
 8095
 8096        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8097        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8098        view.update(cx, |view, cx| {
 8099            view.change_selections(None, cx, |s| {
 8100                s.select_display_ranges([
 8101                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8102                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8103                ])
 8104            });
 8105            view.duplicate_line(&DuplicateLine, cx);
 8106            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8107            assert_eq!(
 8108                view.selections.display_ranges(cx),
 8109                vec![
 8110                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8111                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8112                ]
 8113            );
 8114        });
 8115    }
 8116
 8117    #[gpui::test]
 8118    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8119        cx.set_global(Settings::test(cx));
 8120        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8121        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8122        view.update(cx, |view, cx| {
 8123            view.fold_ranges(
 8124                vec![
 8125                    Point::new(0, 2)..Point::new(1, 2),
 8126                    Point::new(2, 3)..Point::new(4, 1),
 8127                    Point::new(7, 0)..Point::new(8, 4),
 8128                ],
 8129                cx,
 8130            );
 8131            view.change_selections(None, cx, |s| {
 8132                s.select_display_ranges([
 8133                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8134                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8135                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8136                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8137                ])
 8138            });
 8139            assert_eq!(
 8140                view.display_text(cx),
 8141                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8142            );
 8143
 8144            view.move_line_up(&MoveLineUp, cx);
 8145            assert_eq!(
 8146                view.display_text(cx),
 8147                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8148            );
 8149            assert_eq!(
 8150                view.selections.display_ranges(cx),
 8151                vec![
 8152                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8153                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8154                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8155                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8156                ]
 8157            );
 8158        });
 8159
 8160        view.update(cx, |view, cx| {
 8161            view.move_line_down(&MoveLineDown, cx);
 8162            assert_eq!(
 8163                view.display_text(cx),
 8164                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8165            );
 8166            assert_eq!(
 8167                view.selections.display_ranges(cx),
 8168                vec![
 8169                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8170                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8171                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8172                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8173                ]
 8174            );
 8175        });
 8176
 8177        view.update(cx, |view, cx| {
 8178            view.move_line_down(&MoveLineDown, cx);
 8179            assert_eq!(
 8180                view.display_text(cx),
 8181                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8182            );
 8183            assert_eq!(
 8184                view.selections.display_ranges(cx),
 8185                vec![
 8186                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8187                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8188                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8189                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8190                ]
 8191            );
 8192        });
 8193
 8194        view.update(cx, |view, cx| {
 8195            view.move_line_up(&MoveLineUp, cx);
 8196            assert_eq!(
 8197                view.display_text(cx),
 8198                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8199            );
 8200            assert_eq!(
 8201                view.selections.display_ranges(cx),
 8202                vec![
 8203                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8204                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8205                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8206                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8207                ]
 8208            );
 8209        });
 8210    }
 8211
 8212    #[gpui::test]
 8213    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8214        cx.set_global(Settings::test(cx));
 8215        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8216        let snapshot = buffer.read(cx).snapshot(cx);
 8217        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8218        editor.update(cx, |editor, cx| {
 8219            editor.insert_blocks(
 8220                [BlockProperties {
 8221                    style: BlockStyle::Fixed,
 8222                    position: snapshot.anchor_after(Point::new(2, 0)),
 8223                    disposition: BlockDisposition::Below,
 8224                    height: 1,
 8225                    render: Arc::new(|_| Empty::new().boxed()),
 8226                }],
 8227                cx,
 8228            );
 8229            editor.change_selections(None, cx, |s| {
 8230                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8231            });
 8232            editor.move_line_down(&MoveLineDown, cx);
 8233        });
 8234    }
 8235
 8236    #[gpui::test]
 8237    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8238        cx.set_global(Settings::test(cx));
 8239
 8240        cx.add_window(Default::default(), |cx| {
 8241            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8242
 8243            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8244            editor.transpose(&Default::default(), cx);
 8245            assert_eq!(editor.text(cx), "bac");
 8246            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8247
 8248            editor.transpose(&Default::default(), cx);
 8249            assert_eq!(editor.text(cx), "bca");
 8250            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8251
 8252            editor.transpose(&Default::default(), cx);
 8253            assert_eq!(editor.text(cx), "bac");
 8254            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8255
 8256            editor
 8257        })
 8258        .1;
 8259
 8260        cx.add_window(Default::default(), |cx| {
 8261            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8262
 8263            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8264            editor.transpose(&Default::default(), cx);
 8265            assert_eq!(editor.text(cx), "acb\nde");
 8266            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8267
 8268            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8269            editor.transpose(&Default::default(), cx);
 8270            assert_eq!(editor.text(cx), "acbd\ne");
 8271            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8272
 8273            editor.transpose(&Default::default(), cx);
 8274            assert_eq!(editor.text(cx), "acbde\n");
 8275            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8276
 8277            editor.transpose(&Default::default(), cx);
 8278            assert_eq!(editor.text(cx), "acbd\ne");
 8279            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8280
 8281            editor
 8282        })
 8283        .1;
 8284
 8285        cx.add_window(Default::default(), |cx| {
 8286            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8287
 8288            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8289            editor.transpose(&Default::default(), cx);
 8290            assert_eq!(editor.text(cx), "bacd\ne");
 8291            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8292
 8293            editor.transpose(&Default::default(), cx);
 8294            assert_eq!(editor.text(cx), "bcade\n");
 8295            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8296
 8297            editor.transpose(&Default::default(), cx);
 8298            assert_eq!(editor.text(cx), "bcda\ne");
 8299            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8300
 8301            editor.transpose(&Default::default(), cx);
 8302            assert_eq!(editor.text(cx), "bcade\n");
 8303            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8304
 8305            editor.transpose(&Default::default(), cx);
 8306            assert_eq!(editor.text(cx), "bcaed\n");
 8307            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8308
 8309            editor
 8310        })
 8311        .1;
 8312
 8313        cx.add_window(Default::default(), |cx| {
 8314            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8315
 8316            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8317            editor.transpose(&Default::default(), cx);
 8318            assert_eq!(editor.text(cx), "🏀🍐✋");
 8319            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8320
 8321            editor.transpose(&Default::default(), cx);
 8322            assert_eq!(editor.text(cx), "🏀✋🍐");
 8323            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8324
 8325            editor.transpose(&Default::default(), cx);
 8326            assert_eq!(editor.text(cx), "🏀🍐✋");
 8327            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8328
 8329            editor
 8330        })
 8331        .1;
 8332    }
 8333
 8334    #[gpui::test]
 8335    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8336        let mut cx = EditorTestContext::new(cx).await;
 8337
 8338        cx.set_state("[one✅ }two [three }four [five }six ");
 8339        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8340        cx.assert_editor_state("|two |four |six ");
 8341
 8342        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8343        cx.set_state("two |four |six |");
 8344        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8345        cx.assert_editor_state("two one✅ |four three |six five |");
 8346
 8347        // Paste again but with only two cursors. Since the number of cursors doesn't
 8348        // match the number of slices in the clipboard, the entire clipboard text
 8349        // is pasted at each cursor.
 8350        cx.set_state("|two one✅ four three six five |");
 8351        cx.update_editor(|e, cx| {
 8352            e.handle_input("( ", cx);
 8353            e.paste(&Paste, cx);
 8354            e.handle_input(") ", cx);
 8355        });
 8356        cx.assert_editor_state(indoc! {"
 8357            ( one✅ 
 8358            three 
 8359            five ) |two one✅ four three six five ( one✅ 
 8360            three 
 8361            five ) |"});
 8362
 8363        // Cut with three selections, one of which is full-line.
 8364        cx.set_state(indoc! {"
 8365            1[2}3
 8366            4|567
 8367            [8}9"});
 8368        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8369        cx.assert_editor_state(indoc! {"
 8370            1|3
 8371            |9"});
 8372
 8373        // Paste with three selections, noticing how the copied selection that was full-line
 8374        // gets inserted before the second cursor.
 8375        cx.set_state(indoc! {"
 8376            1|3
 8377            9|
 8378            [o}ne"});
 8379        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8380        cx.assert_editor_state(indoc! {"
 8381            12|3
 8382            4567
 8383            9|
 8384            8|ne"});
 8385
 8386        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8387        cx.set_state(indoc! {"
 8388            The quick brown
 8389            fox ju|mps over
 8390            the lazy dog"});
 8391        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8392        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8393
 8394        // Paste with three selections, noticing how the copied full-line selection is inserted
 8395        // before the empty selections but replaces the selection that is non-empty.
 8396        cx.set_state(indoc! {"
 8397            T|he quick brown
 8398            [fo}x jumps over
 8399            t|he lazy dog"});
 8400        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8401        cx.assert_editor_state(indoc! {"
 8402            fox jumps over
 8403            T|he quick brown
 8404            fox jumps over
 8405            |x jumps over
 8406            fox jumps over
 8407            t|he lazy dog"});
 8408    }
 8409
 8410    #[gpui::test]
 8411    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8412        cx.set_global(Settings::test(cx));
 8413        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8414        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8415        view.update(cx, |view, cx| {
 8416            view.select_all(&SelectAll, cx);
 8417            assert_eq!(
 8418                view.selections.display_ranges(cx),
 8419                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8420            );
 8421        });
 8422    }
 8423
 8424    #[gpui::test]
 8425    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8426        cx.set_global(Settings::test(cx));
 8427        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8428        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8429        view.update(cx, |view, cx| {
 8430            view.change_selections(None, cx, |s| {
 8431                s.select_display_ranges([
 8432                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8433                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8434                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8435                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8436                ])
 8437            });
 8438            view.select_line(&SelectLine, cx);
 8439            assert_eq!(
 8440                view.selections.display_ranges(cx),
 8441                vec![
 8442                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8443                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8444                ]
 8445            );
 8446        });
 8447
 8448        view.update(cx, |view, cx| {
 8449            view.select_line(&SelectLine, cx);
 8450            assert_eq!(
 8451                view.selections.display_ranges(cx),
 8452                vec![
 8453                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8454                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8455                ]
 8456            );
 8457        });
 8458
 8459        view.update(cx, |view, cx| {
 8460            view.select_line(&SelectLine, cx);
 8461            assert_eq!(
 8462                view.selections.display_ranges(cx),
 8463                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8464            );
 8465        });
 8466    }
 8467
 8468    #[gpui::test]
 8469    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8470        cx.set_global(Settings::test(cx));
 8471        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8472        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8473        view.update(cx, |view, cx| {
 8474            view.fold_ranges(
 8475                vec![
 8476                    Point::new(0, 2)..Point::new(1, 2),
 8477                    Point::new(2, 3)..Point::new(4, 1),
 8478                    Point::new(7, 0)..Point::new(8, 4),
 8479                ],
 8480                cx,
 8481            );
 8482            view.change_selections(None, cx, |s| {
 8483                s.select_display_ranges([
 8484                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8485                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8486                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8487                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8488                ])
 8489            });
 8490            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8491        });
 8492
 8493        view.update(cx, |view, cx| {
 8494            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8495            assert_eq!(
 8496                view.display_text(cx),
 8497                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8498            );
 8499            assert_eq!(
 8500                view.selections.display_ranges(cx),
 8501                [
 8502                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8503                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8504                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8505                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8506                ]
 8507            );
 8508        });
 8509
 8510        view.update(cx, |view, cx| {
 8511            view.change_selections(None, cx, |s| {
 8512                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 8513            });
 8514            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8515            assert_eq!(
 8516                view.display_text(cx),
 8517                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8518            );
 8519            assert_eq!(
 8520                view.selections.display_ranges(cx),
 8521                [
 8522                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8523                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8524                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8525                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8526                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8527                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8528                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8529                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8530                ]
 8531            );
 8532        });
 8533    }
 8534
 8535    #[gpui::test]
 8536    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8537        cx.set_global(Settings::test(cx));
 8538        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8539        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8540
 8541        view.update(cx, |view, cx| {
 8542            view.change_selections(None, cx, |s| {
 8543                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 8544            });
 8545        });
 8546        view.update(cx, |view, cx| {
 8547            view.add_selection_above(&AddSelectionAbove, cx);
 8548            assert_eq!(
 8549                view.selections.display_ranges(cx),
 8550                vec![
 8551                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8552                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8553                ]
 8554            );
 8555        });
 8556
 8557        view.update(cx, |view, cx| {
 8558            view.add_selection_above(&AddSelectionAbove, cx);
 8559            assert_eq!(
 8560                view.selections.display_ranges(cx),
 8561                vec![
 8562                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8563                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8564                ]
 8565            );
 8566        });
 8567
 8568        view.update(cx, |view, cx| {
 8569            view.add_selection_below(&AddSelectionBelow, cx);
 8570            assert_eq!(
 8571                view.selections.display_ranges(cx),
 8572                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8573            );
 8574
 8575            view.undo_selection(&UndoSelection, cx);
 8576            assert_eq!(
 8577                view.selections.display_ranges(cx),
 8578                vec![
 8579                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8580                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8581                ]
 8582            );
 8583
 8584            view.redo_selection(&RedoSelection, cx);
 8585            assert_eq!(
 8586                view.selections.display_ranges(cx),
 8587                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8588            );
 8589        });
 8590
 8591        view.update(cx, |view, cx| {
 8592            view.add_selection_below(&AddSelectionBelow, cx);
 8593            assert_eq!(
 8594                view.selections.display_ranges(cx),
 8595                vec![
 8596                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8597                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8598                ]
 8599            );
 8600        });
 8601
 8602        view.update(cx, |view, cx| {
 8603            view.add_selection_below(&AddSelectionBelow, cx);
 8604            assert_eq!(
 8605                view.selections.display_ranges(cx),
 8606                vec![
 8607                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8608                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8609                ]
 8610            );
 8611        });
 8612
 8613        view.update(cx, |view, cx| {
 8614            view.change_selections(None, cx, |s| {
 8615                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 8616            });
 8617        });
 8618        view.update(cx, |view, cx| {
 8619            view.add_selection_below(&AddSelectionBelow, cx);
 8620            assert_eq!(
 8621                view.selections.display_ranges(cx),
 8622                vec![
 8623                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8624                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8625                ]
 8626            );
 8627        });
 8628
 8629        view.update(cx, |view, cx| {
 8630            view.add_selection_below(&AddSelectionBelow, cx);
 8631            assert_eq!(
 8632                view.selections.display_ranges(cx),
 8633                vec![
 8634                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8635                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8636                ]
 8637            );
 8638        });
 8639
 8640        view.update(cx, |view, cx| {
 8641            view.add_selection_above(&AddSelectionAbove, cx);
 8642            assert_eq!(
 8643                view.selections.display_ranges(cx),
 8644                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8645            );
 8646        });
 8647
 8648        view.update(cx, |view, cx| {
 8649            view.add_selection_above(&AddSelectionAbove, cx);
 8650            assert_eq!(
 8651                view.selections.display_ranges(cx),
 8652                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8653            );
 8654        });
 8655
 8656        view.update(cx, |view, cx| {
 8657            view.change_selections(None, cx, |s| {
 8658                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 8659            });
 8660            view.add_selection_below(&AddSelectionBelow, cx);
 8661            assert_eq!(
 8662                view.selections.display_ranges(cx),
 8663                vec![
 8664                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8665                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8666                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8667                ]
 8668            );
 8669        });
 8670
 8671        view.update(cx, |view, cx| {
 8672            view.add_selection_below(&AddSelectionBelow, cx);
 8673            assert_eq!(
 8674                view.selections.display_ranges(cx),
 8675                vec![
 8676                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8677                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8678                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8679                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8680                ]
 8681            );
 8682        });
 8683
 8684        view.update(cx, |view, cx| {
 8685            view.add_selection_above(&AddSelectionAbove, cx);
 8686            assert_eq!(
 8687                view.selections.display_ranges(cx),
 8688                vec![
 8689                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8690                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8691                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8692                ]
 8693            );
 8694        });
 8695
 8696        view.update(cx, |view, cx| {
 8697            view.change_selections(None, cx, |s| {
 8698                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 8699            });
 8700        });
 8701        view.update(cx, |view, cx| {
 8702            view.add_selection_above(&AddSelectionAbove, cx);
 8703            assert_eq!(
 8704                view.selections.display_ranges(cx),
 8705                vec![
 8706                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8707                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8708                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8709                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8710                ]
 8711            );
 8712        });
 8713
 8714        view.update(cx, |view, cx| {
 8715            view.add_selection_below(&AddSelectionBelow, cx);
 8716            assert_eq!(
 8717                view.selections.display_ranges(cx),
 8718                vec![
 8719                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8720                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8721                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8722                ]
 8723            );
 8724        });
 8725    }
 8726
 8727    #[gpui::test]
 8728    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8729        cx.set_global(Settings::test(cx));
 8730
 8731        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8732        let buffer = MultiBuffer::build_simple(&text, cx);
 8733        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8734
 8735        view.update(cx, |view, cx| {
 8736            view.change_selections(None, cx, |s| {
 8737                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 8738            });
 8739            view.select_next(
 8740                &SelectNext {
 8741                    replace_newest: false,
 8742                },
 8743                cx,
 8744            );
 8745            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8746
 8747            view.select_next(
 8748                &SelectNext {
 8749                    replace_newest: false,
 8750                },
 8751                cx,
 8752            );
 8753            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8754
 8755            view.undo_selection(&UndoSelection, cx);
 8756            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8757
 8758            view.redo_selection(&RedoSelection, cx);
 8759            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8760
 8761            view.select_next(
 8762                &SelectNext {
 8763                    replace_newest: false,
 8764                },
 8765                cx,
 8766            );
 8767            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 8768
 8769            view.select_next(
 8770                &SelectNext {
 8771                    replace_newest: false,
 8772                },
 8773                cx,
 8774            );
 8775            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 8776        });
 8777    }
 8778
 8779    #[gpui::test]
 8780    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8781        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8782        let language = Arc::new(Language::new(
 8783            LanguageConfig::default(),
 8784            Some(tree_sitter_rust::language()),
 8785        ));
 8786
 8787        let text = r#"
 8788            use mod1::mod2::{mod3, mod4};
 8789
 8790            fn fn_1(param1: bool, param2: &str) {
 8791                let var1 = "text";
 8792            }
 8793        "#
 8794        .unindent();
 8795
 8796        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8797        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8798        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8799        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8800            .await;
 8801
 8802        view.update(cx, |view, cx| {
 8803            view.change_selections(None, cx, |s| {
 8804                s.select_display_ranges([
 8805                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8806                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8807                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8808                ]);
 8809            });
 8810            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8811        });
 8812        assert_eq!(
 8813            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 8814            &[
 8815                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8816                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8817                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8818            ]
 8819        );
 8820
 8821        view.update(cx, |view, cx| {
 8822            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8823        });
 8824        assert_eq!(
 8825            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8826            &[
 8827                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8828                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8829            ]
 8830        );
 8831
 8832        view.update(cx, |view, cx| {
 8833            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8834        });
 8835        assert_eq!(
 8836            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8837            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8838        );
 8839
 8840        // Trying to expand the selected syntax node one more time has no effect.
 8841        view.update(cx, |view, cx| {
 8842            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8843        });
 8844        assert_eq!(
 8845            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8846            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8847        );
 8848
 8849        view.update(cx, |view, cx| {
 8850            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8851        });
 8852        assert_eq!(
 8853            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8854            &[
 8855                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8856                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8857            ]
 8858        );
 8859
 8860        view.update(cx, |view, cx| {
 8861            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8862        });
 8863        assert_eq!(
 8864            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8865            &[
 8866                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8867                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8868                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8869            ]
 8870        );
 8871
 8872        view.update(cx, |view, cx| {
 8873            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8874        });
 8875        assert_eq!(
 8876            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8877            &[
 8878                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8879                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8880                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8881            ]
 8882        );
 8883
 8884        // Trying to shrink the selected syntax node one more time has no effect.
 8885        view.update(cx, |view, cx| {
 8886            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8887        });
 8888        assert_eq!(
 8889            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8890            &[
 8891                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8892                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8893                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8894            ]
 8895        );
 8896
 8897        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8898        // a fold.
 8899        view.update(cx, |view, cx| {
 8900            view.fold_ranges(
 8901                vec![
 8902                    Point::new(0, 21)..Point::new(0, 24),
 8903                    Point::new(3, 20)..Point::new(3, 22),
 8904                ],
 8905                cx,
 8906            );
 8907            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8908        });
 8909        assert_eq!(
 8910            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8911            &[
 8912                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8913                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8914                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8915            ]
 8916        );
 8917    }
 8918
 8919    #[gpui::test]
 8920    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8921        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8922        let language = Arc::new(
 8923            Language::new(
 8924                LanguageConfig {
 8925                    brackets: vec![
 8926                        BracketPair {
 8927                            start: "{".to_string(),
 8928                            end: "}".to_string(),
 8929                            close: false,
 8930                            newline: true,
 8931                        },
 8932                        BracketPair {
 8933                            start: "(".to_string(),
 8934                            end: ")".to_string(),
 8935                            close: false,
 8936                            newline: true,
 8937                        },
 8938                    ],
 8939                    ..Default::default()
 8940                },
 8941                Some(tree_sitter_rust::language()),
 8942            )
 8943            .with_indents_query(
 8944                r#"
 8945                (_ "(" ")" @end) @indent
 8946                (_ "{" "}" @end) @indent
 8947                "#,
 8948            )
 8949            .unwrap(),
 8950        );
 8951
 8952        let text = "fn a() {}";
 8953
 8954        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8955        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8956        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8957        editor
 8958            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8959            .await;
 8960
 8961        editor.update(cx, |editor, cx| {
 8962            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 8963            editor.newline(&Newline, cx);
 8964            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8965            assert_eq!(
 8966                editor.selections.ranges(cx),
 8967                &[
 8968                    Point::new(1, 4)..Point::new(1, 4),
 8969                    Point::new(3, 4)..Point::new(3, 4),
 8970                    Point::new(5, 0)..Point::new(5, 0)
 8971                ]
 8972            );
 8973        });
 8974    }
 8975
 8976    #[gpui::test]
 8977    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8978        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8979        let language = Arc::new(Language::new(
 8980            LanguageConfig {
 8981                brackets: vec![
 8982                    BracketPair {
 8983                        start: "{".to_string(),
 8984                        end: "}".to_string(),
 8985                        close: true,
 8986                        newline: true,
 8987                    },
 8988                    BracketPair {
 8989                        start: "/*".to_string(),
 8990                        end: " */".to_string(),
 8991                        close: true,
 8992                        newline: true,
 8993                    },
 8994                    BracketPair {
 8995                        start: "[".to_string(),
 8996                        end: "]".to_string(),
 8997                        close: false,
 8998                        newline: true,
 8999                    },
 9000                ],
 9001                autoclose_before: "})]".to_string(),
 9002                ..Default::default()
 9003            },
 9004            Some(tree_sitter_rust::language()),
 9005        ));
 9006
 9007        let text = r#"
 9008            a
 9009
 9010            /
 9011
 9012        "#
 9013        .unindent();
 9014
 9015        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9016        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9017        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9018        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9019            .await;
 9020
 9021        view.update(cx, |view, cx| {
 9022            view.change_selections(None, cx, |s| {
 9023                s.select_display_ranges([
 9024                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9025                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9026                ])
 9027            });
 9028
 9029            view.handle_input("{", 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.move_right(&MoveRight, cx);
 9044            view.handle_input("}", cx);
 9045            view.handle_input("}", cx);
 9046            view.handle_input("}", cx);
 9047            assert_eq!(
 9048                view.text(cx),
 9049                "
 9050                {{{}}}}
 9051                {{{}}}}
 9052                /
 9053
 9054                "
 9055                .unindent()
 9056            );
 9057
 9058            view.undo(&Undo, cx);
 9059            view.handle_input("/", cx);
 9060            view.handle_input("*", cx);
 9061            assert_eq!(
 9062                view.text(cx),
 9063                "
 9064                /* */
 9065                /* */
 9066                /
 9067
 9068                "
 9069                .unindent()
 9070            );
 9071
 9072            view.undo(&Undo, cx);
 9073            view.change_selections(None, cx, |s| {
 9074                s.select_display_ranges([
 9075                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9076                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9077                ])
 9078            });
 9079            view.handle_input("*", cx);
 9080            assert_eq!(
 9081                view.text(cx),
 9082                "
 9083                a
 9084
 9085                /*
 9086                *
 9087                "
 9088                .unindent()
 9089            );
 9090
 9091            // Don't autoclose if the next character isn't whitespace and isn't
 9092            // listed in the language's "autoclose_before" section.
 9093            view.finalize_last_transaction(cx);
 9094            view.change_selections(None, cx, |s| {
 9095                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 9096            });
 9097            view.handle_input("{", cx);
 9098            assert_eq!(
 9099                view.text(cx),
 9100                "
 9101                {a
 9102
 9103                /*
 9104                *
 9105                "
 9106                .unindent()
 9107            );
 9108
 9109            view.undo(&Undo, cx);
 9110            view.change_selections(None, cx, |s| {
 9111                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 9112            });
 9113            view.handle_input("{", cx);
 9114            assert_eq!(
 9115                view.text(cx),
 9116                "
 9117                {a}
 9118
 9119                /*
 9120                *
 9121                "
 9122                .unindent()
 9123            );
 9124            assert_eq!(
 9125                view.selections.display_ranges(cx),
 9126                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9127            );
 9128
 9129            view.undo(&Undo, cx);
 9130            view.handle_input("[", cx);
 9131            assert_eq!(
 9132                view.text(cx),
 9133                "
 9134                [a]
 9135                
 9136                /*
 9137                *
 9138                "
 9139                .unindent()
 9140            );
 9141            assert_eq!(
 9142                view.selections.display_ranges(cx),
 9143                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9144            );
 9145
 9146            view.undo(&Undo, cx);
 9147            view.change_selections(None, cx, |s| {
 9148                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9149            });
 9150            view.handle_input("[", cx);
 9151            assert_eq!(
 9152                view.text(cx),
 9153                "
 9154                a[
 9155                
 9156                /*
 9157                *
 9158                "
 9159                .unindent()
 9160            );
 9161            assert_eq!(
 9162                view.selections.display_ranges(cx),
 9163                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9164            );
 9165        });
 9166    }
 9167
 9168    #[gpui::test]
 9169    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9170        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9171        let language = Arc::new(Language::new(
 9172            LanguageConfig {
 9173                brackets: vec![BracketPair {
 9174                    start: "{".to_string(),
 9175                    end: "}".to_string(),
 9176                    close: true,
 9177                    newline: true,
 9178                }],
 9179                ..Default::default()
 9180            },
 9181            Some(tree_sitter_rust::language()),
 9182        ));
 9183
 9184        let text = r#"
 9185            a
 9186            b
 9187            c
 9188        "#
 9189        .unindent();
 9190
 9191        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9192        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9193        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9194        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9195            .await;
 9196
 9197        view.update(cx, |view, cx| {
 9198            view.change_selections(None, cx, |s| {
 9199                s.select_display_ranges([
 9200                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9201                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9202                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9203                ])
 9204            });
 9205
 9206            view.handle_input("{", cx);
 9207            view.handle_input("{", cx);
 9208            view.handle_input("{", cx);
 9209            assert_eq!(
 9210                view.text(cx),
 9211                "
 9212                {{{a}}}
 9213                {{{b}}}
 9214                {{{c}}}
 9215                "
 9216                .unindent()
 9217            );
 9218            assert_eq!(
 9219                view.selections.display_ranges(cx),
 9220                [
 9221                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9222                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9223                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9224                ]
 9225            );
 9226
 9227            view.undo(&Undo, cx);
 9228            assert_eq!(
 9229                view.text(cx),
 9230                "
 9231                a
 9232                b
 9233                c
 9234                "
 9235                .unindent()
 9236            );
 9237            assert_eq!(
 9238                view.selections.display_ranges(cx),
 9239                [
 9240                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9241                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9242                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9243                ]
 9244            );
 9245        });
 9246    }
 9247
 9248    #[gpui::test]
 9249    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9250        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9251        let language = Arc::new(Language::new(
 9252            LanguageConfig {
 9253                brackets: vec![BracketPair {
 9254                    start: "{".to_string(),
 9255                    end: "}".to_string(),
 9256                    close: true,
 9257                    newline: true,
 9258                }],
 9259                autoclose_before: "}".to_string(),
 9260                ..Default::default()
 9261            },
 9262            Some(tree_sitter_rust::language()),
 9263        ));
 9264
 9265        let text = r#"
 9266            a
 9267            b
 9268            c
 9269        "#
 9270        .unindent();
 9271
 9272        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9273        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9274        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9275        editor
 9276            .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9277            .await;
 9278
 9279        editor.update(cx, |editor, cx| {
 9280            editor.change_selections(None, cx, |s| {
 9281                s.select_ranges([
 9282                    Point::new(0, 1)..Point::new(0, 1),
 9283                    Point::new(1, 1)..Point::new(1, 1),
 9284                    Point::new(2, 1)..Point::new(2, 1),
 9285                ])
 9286            });
 9287
 9288            editor.handle_input("{", cx);
 9289            editor.handle_input("{", cx);
 9290            editor.handle_input("_", cx);
 9291            assert_eq!(
 9292                editor.text(cx),
 9293                "
 9294                a{{_}}
 9295                b{{_}}
 9296                c{{_}}
 9297                "
 9298                .unindent()
 9299            );
 9300            assert_eq!(
 9301                editor.selections.ranges::<Point>(cx),
 9302                [
 9303                    Point::new(0, 4)..Point::new(0, 4),
 9304                    Point::new(1, 4)..Point::new(1, 4),
 9305                    Point::new(2, 4)..Point::new(2, 4)
 9306                ]
 9307            );
 9308
 9309            editor.backspace(&Default::default(), cx);
 9310            editor.backspace(&Default::default(), cx);
 9311            assert_eq!(
 9312                editor.text(cx),
 9313                "
 9314                a{}
 9315                b{}
 9316                c{}
 9317                "
 9318                .unindent()
 9319            );
 9320            assert_eq!(
 9321                editor.selections.ranges::<Point>(cx),
 9322                [
 9323                    Point::new(0, 2)..Point::new(0, 2),
 9324                    Point::new(1, 2)..Point::new(1, 2),
 9325                    Point::new(2, 2)..Point::new(2, 2)
 9326                ]
 9327            );
 9328
 9329            editor.delete_to_previous_word_start(&Default::default(), cx);
 9330            assert_eq!(
 9331                editor.text(cx),
 9332                "
 9333                a
 9334                b
 9335                c
 9336                "
 9337                .unindent()
 9338            );
 9339            assert_eq!(
 9340                editor.selections.ranges::<Point>(cx),
 9341                [
 9342                    Point::new(0, 1)..Point::new(0, 1),
 9343                    Point::new(1, 1)..Point::new(1, 1),
 9344                    Point::new(2, 1)..Point::new(2, 1)
 9345                ]
 9346            );
 9347        });
 9348    }
 9349
 9350    #[gpui::test]
 9351    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9352        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9353
 9354        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 9355            a.| b
 9356            a.| b
 9357            a.| b"});
 9358        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9359        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9360
 9361        editor.update(cx, |editor, cx| {
 9362            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9363
 9364            editor
 9365                .insert_snippet(&insertion_ranges, snippet, cx)
 9366                .unwrap();
 9367
 9368            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 9369                let range_markers = ('<', '>');
 9370                let (expected_text, mut selection_ranges_lookup) =
 9371                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 9372                let selection_ranges = selection_ranges_lookup
 9373                    .remove(&range_markers.into())
 9374                    .unwrap();
 9375                assert_eq!(editor.text(cx), expected_text);
 9376                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9377            }
 9378            assert(
 9379                editor,
 9380                cx,
 9381                indoc! {"
 9382                    a.f(<one>, two, <three>) b
 9383                    a.f(<one>, two, <three>) b
 9384                    a.f(<one>, two, <three>) b"},
 9385            );
 9386
 9387            // Can't move earlier than the first tab stop
 9388            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9389            assert(
 9390                editor,
 9391                cx,
 9392                indoc! {"
 9393                    a.f(<one>, two, <three>) b
 9394                    a.f(<one>, two, <three>) b
 9395                    a.f(<one>, two, <three>) b"},
 9396            );
 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            editor.move_to_prev_snippet_tabstop(cx);
 9409            assert(
 9410                editor,
 9411                cx,
 9412                indoc! {"
 9413                    a.f(<one>, two, <three>) b
 9414                    a.f(<one>, two, <three>) b
 9415                    a.f(<one>, two, <three>) b"},
 9416            );
 9417
 9418            assert!(editor.move_to_next_snippet_tabstop(cx));
 9419            assert(
 9420                editor,
 9421                cx,
 9422                indoc! {"
 9423                    a.f(one, <two>, three) b
 9424                    a.f(one, <two>, three) b
 9425                    a.f(one, <two>, three) b"},
 9426            );
 9427            assert!(editor.move_to_next_snippet_tabstop(cx));
 9428            assert(
 9429                editor,
 9430                cx,
 9431                indoc! {"
 9432                    a.f(one, two, three)<> b
 9433                    a.f(one, two, three)<> b
 9434                    a.f(one, two, three)<> b"},
 9435            );
 9436
 9437            // As soon as the last tab stop is reached, snippet state is gone
 9438            editor.move_to_prev_snippet_tabstop(cx);
 9439            assert(
 9440                editor,
 9441                cx,
 9442                indoc! {"
 9443                    a.f(one, two, three)<> b
 9444                    a.f(one, two, three)<> b
 9445                    a.f(one, two, three)<> b"},
 9446            );
 9447        });
 9448    }
 9449
 9450    #[gpui::test]
 9451    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9452        cx.foreground().forbid_parking();
 9453
 9454        let mut language = Language::new(
 9455            LanguageConfig {
 9456                name: "Rust".into(),
 9457                path_suffixes: vec!["rs".to_string()],
 9458                ..Default::default()
 9459            },
 9460            Some(tree_sitter_rust::language()),
 9461        );
 9462        let mut fake_servers = language
 9463            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9464                capabilities: lsp::ServerCapabilities {
 9465                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9466                    ..Default::default()
 9467                },
 9468                ..Default::default()
 9469            }))
 9470            .await;
 9471
 9472        let fs = FakeFs::new(cx.background().clone());
 9473        fs.insert_file("/file.rs", Default::default()).await;
 9474
 9475        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9476        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9477        let buffer = project
 9478            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9479            .await
 9480            .unwrap();
 9481
 9482        cx.foreground().start_waiting();
 9483        let fake_server = fake_servers.next().await.unwrap();
 9484
 9485        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9486        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9487        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9488        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9489
 9490        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9491        fake_server
 9492            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9493                assert_eq!(
 9494                    params.text_document.uri,
 9495                    lsp::Url::from_file_path("/file.rs").unwrap()
 9496                );
 9497                assert_eq!(params.options.tab_size, 4);
 9498                Ok(Some(vec![lsp::TextEdit::new(
 9499                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9500                    ", ".to_string(),
 9501                )]))
 9502            })
 9503            .next()
 9504            .await;
 9505        cx.foreground().start_waiting();
 9506        save.await.unwrap();
 9507        assert_eq!(
 9508            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9509            "one, two\nthree\n"
 9510        );
 9511        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9512
 9513        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9514        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9515
 9516        // Ensure we can still save even if formatting hangs.
 9517        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9518            assert_eq!(
 9519                params.text_document.uri,
 9520                lsp::Url::from_file_path("/file.rs").unwrap()
 9521            );
 9522            futures::future::pending::<()>().await;
 9523            unreachable!()
 9524        });
 9525        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9526        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9527        cx.foreground().start_waiting();
 9528        save.await.unwrap();
 9529        assert_eq!(
 9530            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9531            "one\ntwo\nthree\n"
 9532        );
 9533        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9534
 9535        // Set rust language override and assert overriden tabsize is sent to language server
 9536        cx.update(|cx| {
 9537            cx.update_global::<Settings, _, _>(|settings, _| {
 9538                settings.language_overrides.insert(
 9539                    "Rust".into(),
 9540                    EditorSettings {
 9541                        tab_size: Some(8.try_into().unwrap()),
 9542                        ..Default::default()
 9543                    },
 9544                );
 9545            })
 9546        });
 9547
 9548        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9549        fake_server
 9550            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9551                assert_eq!(
 9552                    params.text_document.uri,
 9553                    lsp::Url::from_file_path("/file.rs").unwrap()
 9554                );
 9555                assert_eq!(params.options.tab_size, 8);
 9556                Ok(Some(vec![]))
 9557            })
 9558            .next()
 9559            .await;
 9560        cx.foreground().start_waiting();
 9561        save.await.unwrap();
 9562    }
 9563
 9564    #[gpui::test]
 9565    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
 9566        cx.foreground().forbid_parking();
 9567
 9568        let mut language = Language::new(
 9569            LanguageConfig {
 9570                name: "Rust".into(),
 9571                path_suffixes: vec!["rs".to_string()],
 9572                ..Default::default()
 9573            },
 9574            Some(tree_sitter_rust::language()),
 9575        );
 9576        let mut fake_servers = language
 9577            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9578                capabilities: lsp::ServerCapabilities {
 9579                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
 9580                    ..Default::default()
 9581                },
 9582                ..Default::default()
 9583            }))
 9584            .await;
 9585
 9586        let fs = FakeFs::new(cx.background().clone());
 9587        fs.insert_file("/file.rs", Default::default()).await;
 9588
 9589        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9590        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9591        let buffer = project
 9592            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9593            .await
 9594            .unwrap();
 9595
 9596        cx.foreground().start_waiting();
 9597        let fake_server = fake_servers.next().await.unwrap();
 9598
 9599        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9600        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9601        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9602        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9603
 9604        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9605        fake_server
 9606            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9607                assert_eq!(
 9608                    params.text_document.uri,
 9609                    lsp::Url::from_file_path("/file.rs").unwrap()
 9610                );
 9611                assert_eq!(params.options.tab_size, 4);
 9612                Ok(Some(vec![lsp::TextEdit::new(
 9613                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9614                    ", ".to_string(),
 9615                )]))
 9616            })
 9617            .next()
 9618            .await;
 9619        cx.foreground().start_waiting();
 9620        save.await.unwrap();
 9621        assert_eq!(
 9622            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9623            "one, two\nthree\n"
 9624        );
 9625        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9626
 9627        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9628        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9629
 9630        // Ensure we can still save even if formatting hangs.
 9631        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
 9632            move |params, _| async move {
 9633                assert_eq!(
 9634                    params.text_document.uri,
 9635                    lsp::Url::from_file_path("/file.rs").unwrap()
 9636                );
 9637                futures::future::pending::<()>().await;
 9638                unreachable!()
 9639            },
 9640        );
 9641        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9642        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9643        cx.foreground().start_waiting();
 9644        save.await.unwrap();
 9645        assert_eq!(
 9646            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9647            "one\ntwo\nthree\n"
 9648        );
 9649        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9650
 9651        // Set rust language override and assert overriden tabsize is sent to language server
 9652        cx.update(|cx| {
 9653            cx.update_global::<Settings, _, _>(|settings, _| {
 9654                settings.language_overrides.insert(
 9655                    "Rust".into(),
 9656                    EditorSettings {
 9657                        tab_size: Some(8.try_into().unwrap()),
 9658                        ..Default::default()
 9659                    },
 9660                );
 9661            })
 9662        });
 9663
 9664        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9665        fake_server
 9666            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9667                assert_eq!(
 9668                    params.text_document.uri,
 9669                    lsp::Url::from_file_path("/file.rs").unwrap()
 9670                );
 9671                assert_eq!(params.options.tab_size, 8);
 9672                Ok(Some(vec![]))
 9673            })
 9674            .next()
 9675            .await;
 9676        cx.foreground().start_waiting();
 9677        save.await.unwrap();
 9678    }
 9679
 9680    #[gpui::test]
 9681    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9682        let mut cx = EditorLspTestContext::new_rust(
 9683            lsp::ServerCapabilities {
 9684                completion_provider: Some(lsp::CompletionOptions {
 9685                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9686                    ..Default::default()
 9687                }),
 9688                ..Default::default()
 9689            },
 9690            cx,
 9691        )
 9692        .await;
 9693
 9694        cx.set_state(indoc! {"
 9695            one|
 9696            two
 9697            three"});
 9698        cx.simulate_keystroke(".");
 9699        handle_completion_request(
 9700            &mut cx,
 9701            indoc! {"
 9702                one.|<>
 9703                two
 9704                three"},
 9705            vec!["first_completion", "second_completion"],
 9706        )
 9707        .await;
 9708        cx.condition(|editor, _| editor.context_menu_visible())
 9709            .await;
 9710        let apply_additional_edits = cx.update_editor(|editor, cx| {
 9711            editor.move_down(&MoveDown, cx);
 9712            editor
 9713                .confirm_completion(&ConfirmCompletion::default(), cx)
 9714                .unwrap()
 9715        });
 9716        cx.assert_editor_state(indoc! {"
 9717            one.second_completion|
 9718            two
 9719            three"});
 9720
 9721        handle_resolve_completion_request(
 9722            &mut cx,
 9723            Some((
 9724                indoc! {"
 9725                    one.second_completion
 9726                    two
 9727                    three<>"},
 9728                "\nadditional edit",
 9729            )),
 9730        )
 9731        .await;
 9732        apply_additional_edits.await.unwrap();
 9733        cx.assert_editor_state(indoc! {"
 9734            one.second_completion|
 9735            two
 9736            three
 9737            additional edit"});
 9738
 9739        cx.set_state(indoc! {"
 9740            one.second_completion
 9741            two|
 9742            three|
 9743            additional edit"});
 9744        cx.simulate_keystroke(" ");
 9745        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9746        cx.simulate_keystroke("s");
 9747        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9748
 9749        cx.assert_editor_state(indoc! {"
 9750            one.second_completion
 9751            two s|
 9752            three s|
 9753            additional edit"});
 9754        handle_completion_request(
 9755            &mut cx,
 9756            indoc! {"
 9757                one.second_completion
 9758                two s
 9759                three <s|>
 9760                additional edit"},
 9761            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
 9762        )
 9763        .await;
 9764        cx.condition(|editor, _| editor.context_menu_visible())
 9765            .await;
 9766
 9767        cx.simulate_keystroke("i");
 9768
 9769        handle_completion_request(
 9770            &mut cx,
 9771            indoc! {"
 9772                one.second_completion
 9773                two si
 9774                three <si|>
 9775                additional edit"},
 9776            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
 9777        )
 9778        .await;
 9779        cx.condition(|editor, _| editor.context_menu_visible())
 9780            .await;
 9781
 9782        let apply_additional_edits = cx.update_editor(|editor, cx| {
 9783            editor
 9784                .confirm_completion(&ConfirmCompletion::default(), cx)
 9785                .unwrap()
 9786        });
 9787        cx.assert_editor_state(indoc! {"
 9788            one.second_completion
 9789            two sixth_completion|
 9790            three sixth_completion|
 9791            additional edit"});
 9792
 9793        handle_resolve_completion_request(&mut cx, None).await;
 9794        apply_additional_edits.await.unwrap();
 9795
 9796        cx.update(|cx| {
 9797            cx.update_global::<Settings, _, _>(|settings, _| {
 9798                settings.show_completions_on_input = false;
 9799            })
 9800        });
 9801        cx.set_state("editor|");
 9802        cx.simulate_keystroke(".");
 9803        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9804        cx.simulate_keystrokes(["c", "l", "o"]);
 9805        cx.assert_editor_state("editor.clo|");
 9806        assert!(cx.editor(|e, _| e.context_menu.is_none()));
 9807        cx.update_editor(|editor, cx| {
 9808            editor.show_completions(&ShowCompletions, cx);
 9809        });
 9810        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
 9811        cx.condition(|editor, _| editor.context_menu_visible())
 9812            .await;
 9813        let apply_additional_edits = cx.update_editor(|editor, cx| {
 9814            editor
 9815                .confirm_completion(&ConfirmCompletion::default(), cx)
 9816                .unwrap()
 9817        });
 9818        cx.assert_editor_state("editor.close|");
 9819        handle_resolve_completion_request(&mut cx, None).await;
 9820        apply_additional_edits.await.unwrap();
 9821
 9822        // Handle completion request passing a marked string specifying where the completion
 9823        // should be triggered from using '|' character, what range should be replaced, and what completions
 9824        // should be returned using '<' and '>' to delimit the range
 9825        async fn handle_completion_request<'a>(
 9826            cx: &mut EditorLspTestContext<'a>,
 9827            marked_string: &str,
 9828            completions: Vec<&'static str>,
 9829        ) {
 9830            let complete_from_marker: TextRangeMarker = '|'.into();
 9831            let replace_range_marker: TextRangeMarker = ('<', '>').into();
 9832            let (_, mut marked_ranges) = marked_text_ranges_by(
 9833                marked_string,
 9834                vec![complete_from_marker.clone(), replace_range_marker.clone()],
 9835            );
 9836
 9837            let complete_from_position =
 9838                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
 9839            let replace_range =
 9840                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
 9841
 9842            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
 9843                let completions = completions.clone();
 9844                async move {
 9845                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
 9846                    assert_eq!(
 9847                        params.text_document_position.position,
 9848                        complete_from_position
 9849                    );
 9850                    Ok(Some(lsp::CompletionResponse::Array(
 9851                        completions
 9852                            .iter()
 9853                            .map(|completion_text| lsp::CompletionItem {
 9854                                label: completion_text.to_string(),
 9855                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9856                                    range: replace_range.clone(),
 9857                                    new_text: completion_text.to_string(),
 9858                                })),
 9859                                ..Default::default()
 9860                            })
 9861                            .collect(),
 9862                    )))
 9863                }
 9864            })
 9865            .next()
 9866            .await;
 9867        }
 9868
 9869        async fn handle_resolve_completion_request<'a>(
 9870            cx: &mut EditorLspTestContext<'a>,
 9871            edit: Option<(&'static str, &'static str)>,
 9872        ) {
 9873            let edit = edit.map(|(marked_string, new_text)| {
 9874                let replace_range_marker: TextRangeMarker = ('<', '>').into();
 9875                let (_, mut marked_ranges) =
 9876                    marked_text_ranges_by(marked_string, vec![replace_range_marker.clone()]);
 9877
 9878                let replace_range = cx
 9879                    .to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
 9880
 9881                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
 9882            });
 9883
 9884            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
 9885                let edit = edit.clone();
 9886                async move {
 9887                    Ok(lsp::CompletionItem {
 9888                        additional_text_edits: edit,
 9889                        ..Default::default()
 9890                    })
 9891                }
 9892            })
 9893            .next()
 9894            .await;
 9895        }
 9896    }
 9897
 9898    #[gpui::test]
 9899    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9900        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9901        let language = Arc::new(Language::new(
 9902            LanguageConfig {
 9903                line_comment: Some("// ".to_string()),
 9904                ..Default::default()
 9905            },
 9906            Some(tree_sitter_rust::language()),
 9907        ));
 9908
 9909        let text = "
 9910            fn a() {
 9911                //b();
 9912                // c();
 9913                //  d();
 9914            }
 9915        "
 9916        .unindent();
 9917
 9918        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9919        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9920        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9921
 9922        view.update(cx, |editor, cx| {
 9923            // If multiple selections intersect a line, the line is only
 9924            // toggled once.
 9925            editor.change_selections(None, cx, |s| {
 9926                s.select_display_ranges([
 9927                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9928                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9929                ])
 9930            });
 9931            editor.toggle_comments(&ToggleComments, cx);
 9932            assert_eq!(
 9933                editor.text(cx),
 9934                "
 9935                    fn a() {
 9936                        b();
 9937                        c();
 9938                         d();
 9939                    }
 9940                "
 9941                .unindent()
 9942            );
 9943
 9944            // The comment prefix is inserted at the same column for every line
 9945            // in a selection.
 9946            editor.change_selections(None, cx, |s| {
 9947                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
 9948            });
 9949            editor.toggle_comments(&ToggleComments, cx);
 9950            assert_eq!(
 9951                editor.text(cx),
 9952                "
 9953                    fn a() {
 9954                        // b();
 9955                        // c();
 9956                        //  d();
 9957                    }
 9958                "
 9959                .unindent()
 9960            );
 9961
 9962            // If a selection ends at the beginning of a line, that line is not toggled.
 9963            editor.change_selections(None, cx, |s| {
 9964                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
 9965            });
 9966            editor.toggle_comments(&ToggleComments, cx);
 9967            assert_eq!(
 9968                editor.text(cx),
 9969                "
 9970                        fn a() {
 9971                            // b();
 9972                            c();
 9973                            //  d();
 9974                        }
 9975                    "
 9976                .unindent()
 9977            );
 9978        });
 9979    }
 9980
 9981    #[gpui::test]
 9982    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9983        cx.set_global(Settings::test(cx));
 9984        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9985        let multibuffer = cx.add_model(|cx| {
 9986            let mut multibuffer = MultiBuffer::new(0);
 9987            multibuffer.push_excerpts(
 9988                buffer.clone(),
 9989                [
 9990                    ExcerptRange {
 9991                        context: Point::new(0, 0)..Point::new(0, 4),
 9992                        primary: None,
 9993                    },
 9994                    ExcerptRange {
 9995                        context: Point::new(1, 0)..Point::new(1, 4),
 9996                        primary: None,
 9997                    },
 9998                ],
 9999                cx,
10000            );
10001            multibuffer
10002        });
10003
10004        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
10005
10006        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10007        view.update(cx, |view, cx| {
10008            assert_eq!(view.text(cx), "aaaa\nbbbb");
10009            view.change_selections(None, cx, |s| {
10010                s.select_ranges([
10011                    Point::new(0, 0)..Point::new(0, 0),
10012                    Point::new(1, 0)..Point::new(1, 0),
10013                ])
10014            });
10015
10016            view.handle_input("X", cx);
10017            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
10018            assert_eq!(
10019                view.selections.ranges(cx),
10020                [
10021                    Point::new(0, 1)..Point::new(0, 1),
10022                    Point::new(1, 1)..Point::new(1, 1),
10023                ]
10024            )
10025        });
10026    }
10027
10028    #[gpui::test]
10029    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
10030        cx.set_global(Settings::test(cx));
10031        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
10032                [aaaa
10033                (bbbb]
10034                cccc)"});
10035        let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
10036            context,
10037            primary: None,
10038        });
10039        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
10040        let multibuffer = cx.add_model(|cx| {
10041            let mut multibuffer = MultiBuffer::new(0);
10042            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
10043            multibuffer
10044        });
10045
10046        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10047        view.update(cx, |view, cx| {
10048            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
10049                aaaa
10050                b|bbb
10051                b|bb|b
10052                cccc"});
10053            assert_eq!(view.text(cx), expected_text);
10054            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
10055
10056            view.handle_input("X", cx);
10057
10058            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10059                aaaa
10060                bX|bbXb
10061                bX|bbX|b
10062                cccc"});
10063            assert_eq!(view.text(cx), expected_text);
10064            assert_eq!(view.selections.ranges(cx), expected_selections);
10065
10066            view.newline(&Newline, cx);
10067            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10068                aaaa
10069                bX
10070                |bbX
10071                b
10072                bX
10073                |bbX
10074                |b
10075                cccc"});
10076            assert_eq!(view.text(cx), expected_text);
10077            assert_eq!(view.selections.ranges(cx), expected_selections);
10078        });
10079    }
10080
10081    #[gpui::test]
10082    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
10083        cx.set_global(Settings::test(cx));
10084        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10085        let mut excerpt1_id = None;
10086        let multibuffer = cx.add_model(|cx| {
10087            let mut multibuffer = MultiBuffer::new(0);
10088            excerpt1_id = multibuffer
10089                .push_excerpts(
10090                    buffer.clone(),
10091                    [
10092                        ExcerptRange {
10093                            context: Point::new(0, 0)..Point::new(1, 4),
10094                            primary: None,
10095                        },
10096                        ExcerptRange {
10097                            context: Point::new(1, 0)..Point::new(2, 4),
10098                            primary: None,
10099                        },
10100                    ],
10101                    cx,
10102                )
10103                .into_iter()
10104                .next();
10105            multibuffer
10106        });
10107        assert_eq!(
10108            multibuffer.read(cx).read(cx).text(),
10109            "aaaa\nbbbb\nbbbb\ncccc"
10110        );
10111        let (_, editor) = cx.add_window(Default::default(), |cx| {
10112            let mut editor = build_editor(multibuffer.clone(), cx);
10113            let snapshot = editor.snapshot(cx);
10114            editor.change_selections(None, cx, |s| {
10115                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
10116            });
10117            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
10118            assert_eq!(
10119                editor.selections.ranges(cx),
10120                [
10121                    Point::new(1, 3)..Point::new(1, 3),
10122                    Point::new(2, 1)..Point::new(2, 1),
10123                ]
10124            );
10125            editor
10126        });
10127
10128        // Refreshing selections is a no-op when excerpts haven't changed.
10129        editor.update(cx, |editor, cx| {
10130            editor.change_selections(None, cx, |s| {
10131                s.refresh();
10132            });
10133            assert_eq!(
10134                editor.selections.ranges(cx),
10135                [
10136                    Point::new(1, 3)..Point::new(1, 3),
10137                    Point::new(2, 1)..Point::new(2, 1),
10138                ]
10139            );
10140        });
10141
10142        multibuffer.update(cx, |multibuffer, cx| {
10143            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10144        });
10145        editor.update(cx, |editor, cx| {
10146            // Removing an excerpt causes the first selection to become degenerate.
10147            assert_eq!(
10148                editor.selections.ranges(cx),
10149                [
10150                    Point::new(0, 0)..Point::new(0, 0),
10151                    Point::new(0, 1)..Point::new(0, 1)
10152                ]
10153            );
10154
10155            // Refreshing selections will relocate the first selection to the original buffer
10156            // location.
10157            editor.change_selections(None, cx, |s| {
10158                s.refresh();
10159            });
10160            assert_eq!(
10161                editor.selections.ranges(cx),
10162                [
10163                    Point::new(0, 1)..Point::new(0, 1),
10164                    Point::new(0, 3)..Point::new(0, 3)
10165                ]
10166            );
10167            assert!(editor.selections.pending_anchor().is_some());
10168        });
10169    }
10170
10171    #[gpui::test]
10172    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10173        cx.set_global(Settings::test(cx));
10174        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10175        let mut excerpt1_id = None;
10176        let multibuffer = cx.add_model(|cx| {
10177            let mut multibuffer = MultiBuffer::new(0);
10178            excerpt1_id = multibuffer
10179                .push_excerpts(
10180                    buffer.clone(),
10181                    [
10182                        ExcerptRange {
10183                            context: Point::new(0, 0)..Point::new(1, 4),
10184                            primary: None,
10185                        },
10186                        ExcerptRange {
10187                            context: Point::new(1, 0)..Point::new(2, 4),
10188                            primary: None,
10189                        },
10190                    ],
10191                    cx,
10192                )
10193                .into_iter()
10194                .next();
10195            multibuffer
10196        });
10197        assert_eq!(
10198            multibuffer.read(cx).read(cx).text(),
10199            "aaaa\nbbbb\nbbbb\ncccc"
10200        );
10201        let (_, editor) = cx.add_window(Default::default(), |cx| {
10202            let mut editor = build_editor(multibuffer.clone(), cx);
10203            let snapshot = editor.snapshot(cx);
10204            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10205            assert_eq!(
10206                editor.selections.ranges(cx),
10207                [Point::new(1, 3)..Point::new(1, 3)]
10208            );
10209            editor
10210        });
10211
10212        multibuffer.update(cx, |multibuffer, cx| {
10213            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10214        });
10215        editor.update(cx, |editor, cx| {
10216            assert_eq!(
10217                editor.selections.ranges(cx),
10218                [Point::new(0, 0)..Point::new(0, 0)]
10219            );
10220
10221            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10222            editor.change_selections(None, cx, |s| {
10223                s.refresh();
10224            });
10225            assert_eq!(
10226                editor.selections.ranges(cx),
10227                [Point::new(0, 3)..Point::new(0, 3)]
10228            );
10229            assert!(editor.selections.pending_anchor().is_some());
10230        });
10231    }
10232
10233    #[gpui::test]
10234    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10235        cx.update(|cx| cx.set_global(Settings::test(cx)));
10236        let language = Arc::new(
10237            Language::new(
10238                LanguageConfig {
10239                    brackets: vec![
10240                        BracketPair {
10241                            start: "{".to_string(),
10242                            end: "}".to_string(),
10243                            close: true,
10244                            newline: true,
10245                        },
10246                        BracketPair {
10247                            start: "/* ".to_string(),
10248                            end: " */".to_string(),
10249                            close: true,
10250                            newline: true,
10251                        },
10252                    ],
10253                    ..Default::default()
10254                },
10255                Some(tree_sitter_rust::language()),
10256            )
10257            .with_indents_query("")
10258            .unwrap(),
10259        );
10260
10261        let text = concat!(
10262            "{   }\n",     // Suppress rustfmt
10263            "  x\n",       //
10264            "  /*   */\n", //
10265            "x\n",         //
10266            "{{} }\n",     //
10267        );
10268
10269        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10270        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10271        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10272        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10273            .await;
10274
10275        view.update(cx, |view, cx| {
10276            view.change_selections(None, cx, |s| {
10277                s.select_display_ranges([
10278                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10279                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10280                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10281                ])
10282            });
10283            view.newline(&Newline, cx);
10284
10285            assert_eq!(
10286                view.buffer().read(cx).read(cx).text(),
10287                concat!(
10288                    "{ \n",    // Suppress rustfmt
10289                    "\n",      //
10290                    "}\n",     //
10291                    "  x\n",   //
10292                    "  /* \n", //
10293                    "  \n",    //
10294                    "  */\n",  //
10295                    "x\n",     //
10296                    "{{} \n",  //
10297                    "}\n",     //
10298                )
10299            );
10300        });
10301    }
10302
10303    #[gpui::test]
10304    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10305        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10306
10307        cx.set_global(Settings::test(cx));
10308        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10309
10310        editor.update(cx, |editor, cx| {
10311            struct Type1;
10312            struct Type2;
10313
10314            let buffer = buffer.read(cx).snapshot(cx);
10315
10316            let anchor_range = |range: Range<Point>| {
10317                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10318            };
10319
10320            editor.highlight_background::<Type1>(
10321                vec![
10322                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10323                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10324                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10325                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10326                ],
10327                |_| Color::red(),
10328                cx,
10329            );
10330            editor.highlight_background::<Type2>(
10331                vec![
10332                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10333                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10334                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10335                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10336                ],
10337                |_| Color::green(),
10338                cx,
10339            );
10340
10341            let snapshot = editor.snapshot(cx);
10342            let mut highlighted_ranges = editor.background_highlights_in_range(
10343                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10344                &snapshot,
10345                cx.global::<Settings>().theme.as_ref(),
10346            );
10347            // Enforce a consistent ordering based on color without relying on the ordering of the
10348            // highlight's `TypeId` which is non-deterministic.
10349            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10350            assert_eq!(
10351                highlighted_ranges,
10352                &[
10353                    (
10354                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10355                        Color::green(),
10356                    ),
10357                    (
10358                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10359                        Color::green(),
10360                    ),
10361                    (
10362                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10363                        Color::red(),
10364                    ),
10365                    (
10366                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10367                        Color::red(),
10368                    ),
10369                ]
10370            );
10371            assert_eq!(
10372                editor.background_highlights_in_range(
10373                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10374                    &snapshot,
10375                    cx.global::<Settings>().theme.as_ref(),
10376                ),
10377                &[(
10378                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10379                    Color::red(),
10380                )]
10381            );
10382        });
10383    }
10384
10385    #[gpui::test]
10386    fn test_following(cx: &mut gpui::MutableAppContext) {
10387        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10388
10389        cx.set_global(Settings::test(cx));
10390
10391        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10392        let (_, follower) = cx.add_window(
10393            WindowOptions {
10394                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10395                ..Default::default()
10396            },
10397            |cx| build_editor(buffer.clone(), cx),
10398        );
10399
10400        let pending_update = Rc::new(RefCell::new(None));
10401        follower.update(cx, {
10402            let update = pending_update.clone();
10403            |_, cx| {
10404                cx.subscribe(&leader, move |_, leader, event, cx| {
10405                    leader
10406                        .read(cx)
10407                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10408                })
10409                .detach();
10410            }
10411        });
10412
10413        // Update the selections only
10414        leader.update(cx, |leader, cx| {
10415            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10416        });
10417        follower.update(cx, |follower, cx| {
10418            follower
10419                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10420                .unwrap();
10421        });
10422        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
10423
10424        // Update the scroll position only
10425        leader.update(cx, |leader, cx| {
10426            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10427        });
10428        follower.update(cx, |follower, cx| {
10429            follower
10430                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10431                .unwrap();
10432        });
10433        assert_eq!(
10434            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10435            vec2f(1.5, 3.5)
10436        );
10437
10438        // Update the selections and scroll position
10439        leader.update(cx, |leader, cx| {
10440            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
10441            leader.request_autoscroll(Autoscroll::Newest, cx);
10442            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10443        });
10444        follower.update(cx, |follower, cx| {
10445            let initial_scroll_position = follower.scroll_position(cx);
10446            follower
10447                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10448                .unwrap();
10449            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10450            assert!(follower.autoscroll_request.is_some());
10451        });
10452        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
10453
10454        // Creating a pending selection that precedes another selection
10455        leader.update(cx, |leader, cx| {
10456            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10457            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10458        });
10459        follower.update(cx, |follower, cx| {
10460            follower
10461                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10462                .unwrap();
10463        });
10464        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
10465
10466        // Extend the pending selection so that it surrounds another selection
10467        leader.update(cx, |leader, cx| {
10468            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10469        });
10470        follower.update(cx, |follower, cx| {
10471            follower
10472                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10473                .unwrap();
10474        });
10475        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
10476    }
10477
10478    #[test]
10479    fn test_combine_syntax_and_fuzzy_match_highlights() {
10480        let string = "abcdefghijklmnop";
10481        let syntax_ranges = [
10482            (
10483                0..3,
10484                HighlightStyle {
10485                    color: Some(Color::red()),
10486                    ..Default::default()
10487                },
10488            ),
10489            (
10490                4..8,
10491                HighlightStyle {
10492                    color: Some(Color::green()),
10493                    ..Default::default()
10494                },
10495            ),
10496        ];
10497        let match_indices = [4, 6, 7, 8];
10498        assert_eq!(
10499            combine_syntax_and_fuzzy_match_highlights(
10500                &string,
10501                Default::default(),
10502                syntax_ranges.into_iter(),
10503                &match_indices,
10504            ),
10505            &[
10506                (
10507                    0..3,
10508                    HighlightStyle {
10509                        color: Some(Color::red()),
10510                        ..Default::default()
10511                    },
10512                ),
10513                (
10514                    4..5,
10515                    HighlightStyle {
10516                        color: Some(Color::green()),
10517                        weight: Some(fonts::Weight::BOLD),
10518                        ..Default::default()
10519                    },
10520                ),
10521                (
10522                    5..6,
10523                    HighlightStyle {
10524                        color: Some(Color::green()),
10525                        ..Default::default()
10526                    },
10527                ),
10528                (
10529                    6..8,
10530                    HighlightStyle {
10531                        color: Some(Color::green()),
10532                        weight: Some(fonts::Weight::BOLD),
10533                        ..Default::default()
10534                    },
10535                ),
10536                (
10537                    8..9,
10538                    HighlightStyle {
10539                        weight: Some(fonts::Weight::BOLD),
10540                        ..Default::default()
10541                    },
10542                ),
10543            ]
10544        );
10545    }
10546
10547    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10548        let point = DisplayPoint::new(row as u32, column as u32);
10549        point..point
10550    }
10551
10552    fn assert_selection_ranges(
10553        marked_text: &str,
10554        selection_marker_pairs: Vec<(char, char)>,
10555        view: &mut Editor,
10556        cx: &mut ViewContext<Editor>,
10557    ) {
10558        let snapshot = view.snapshot(cx).display_snapshot;
10559        let mut marker_chars = Vec::new();
10560        for (start, end) in selection_marker_pairs.iter() {
10561            marker_chars.push(*start);
10562            marker_chars.push(*end);
10563        }
10564        let (_, markers) = marked_text_by(marked_text, marker_chars);
10565        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10566            .iter()
10567            .map(|(start, end)| {
10568                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10569                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10570                start..end
10571            })
10572            .collect();
10573        assert_eq!(
10574            view.selections.display_ranges(cx),
10575            &asserted_ranges[..],
10576            "Assert selections are {}",
10577            marked_text
10578        );
10579    }
10580}
10581
10582trait RangeExt<T> {
10583    fn sorted(&self) -> Range<T>;
10584    fn to_inclusive(&self) -> RangeInclusive<T>;
10585}
10586
10587impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10588    fn sorted(&self) -> Self {
10589        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10590    }
10591
10592    fn to_inclusive(&self) -> RangeInclusive<T> {
10593        self.start.clone()..=self.end.clone()
10594    }
10595}
10596
10597trait RangeToAnchorExt {
10598    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10599}
10600
10601impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10602    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10603        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10604    }
10605}