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