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