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