editor.rs

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