editor.rs

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