editor.rs

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