editor.rs

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