editor.rs

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