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 = futures::future::join(
 5595                            cx.background().timer(Duration::from_millis(milliseconds)),
 5596                            pending_autosave,
 5597                        )
 5598                        .fuse();
 5599                        futures::select! {
 5600                            _ = timer => {}
 5601                            _ = cancel_rx => return None,
 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) && !self.buffer.read(cx).has_conflict(cx) {
 5638                return workspace::Item::save(self, project, cx);
 5639            }
 5640        }
 5641
 5642        Task::ready(Ok(()))
 5643    }
 5644
 5645    pub fn set_searchable(&mut self, searchable: bool) {
 5646        self.searchable = searchable;
 5647    }
 5648
 5649    pub fn searchable(&self) -> bool {
 5650        self.searchable
 5651    }
 5652
 5653    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5654        let active_item = workspace.active_item(cx);
 5655        let editor_handle = if let Some(editor) = active_item
 5656            .as_ref()
 5657            .and_then(|item| item.act_as::<Self>(cx))
 5658        {
 5659            editor
 5660        } else {
 5661            cx.propagate_action();
 5662            return;
 5663        };
 5664
 5665        let editor = editor_handle.read(cx);
 5666        let buffer = editor.buffer.read(cx);
 5667        if buffer.is_singleton() {
 5668            cx.propagate_action();
 5669            return;
 5670        }
 5671
 5672        let mut new_selections_by_buffer = HashMap::default();
 5673        for selection in editor.selections.all::<usize>(cx) {
 5674            for (buffer, mut range) in
 5675                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5676            {
 5677                if selection.reversed {
 5678                    mem::swap(&mut range.start, &mut range.end);
 5679                }
 5680                new_selections_by_buffer
 5681                    .entry(buffer)
 5682                    .or_insert(Vec::new())
 5683                    .push(range)
 5684            }
 5685        }
 5686
 5687        editor_handle.update(cx, |editor, cx| {
 5688            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 5689        });
 5690        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 5691        nav_history.borrow_mut().disable();
 5692
 5693        // We defer the pane interaction because we ourselves are a workspace item
 5694        // and activating a new item causes the pane to call a method on us reentrantly,
 5695        // which panics if we're on the stack.
 5696        cx.defer(move |workspace, cx| {
 5697            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5698                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5699                editor.update(cx, |editor, cx| {
 5700                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5701                        s.select_ranges(ranges);
 5702                    });
 5703                });
 5704            }
 5705
 5706            nav_history.borrow_mut().enable();
 5707        });
 5708    }
 5709
 5710    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
 5711        let editor = workspace.open_path(action.path.clone(), true, cx);
 5712        let position = action.position;
 5713        let anchor = action.anchor;
 5714        cx.spawn_weak(|_, mut cx| async move {
 5715            let editor = editor.await.log_err()?.downcast::<Editor>()?;
 5716            editor.update(&mut cx, |editor, cx| {
 5717                let buffer = editor.buffer().read(cx).as_singleton()?;
 5718                let buffer = buffer.read(cx);
 5719                let cursor = if buffer.can_resolve(&anchor) {
 5720                    language::ToPoint::to_point(&anchor, buffer)
 5721                } else {
 5722                    buffer.clip_point(position, Bias::Left)
 5723                };
 5724
 5725                let nav_history = editor.nav_history.take();
 5726                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5727                    s.select_ranges([cursor..cursor]);
 5728                });
 5729                editor.nav_history = nav_history;
 5730
 5731                Some(())
 5732            })?;
 5733            Some(())
 5734        })
 5735        .detach()
 5736    }
 5737}
 5738
 5739impl EditorSnapshot {
 5740    pub fn is_focused(&self) -> bool {
 5741        self.is_focused
 5742    }
 5743
 5744    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5745        self.placeholder_text.as_ref()
 5746    }
 5747
 5748    pub fn scroll_position(&self) -> Vector2F {
 5749        compute_scroll_position(
 5750            &self.display_snapshot,
 5751            self.scroll_position,
 5752            &self.scroll_top_anchor,
 5753        )
 5754    }
 5755}
 5756
 5757impl Deref for EditorSnapshot {
 5758    type Target = DisplaySnapshot;
 5759
 5760    fn deref(&self) -> &Self::Target {
 5761        &self.display_snapshot
 5762    }
 5763}
 5764
 5765fn compute_scroll_position(
 5766    snapshot: &DisplaySnapshot,
 5767    mut scroll_position: Vector2F,
 5768    scroll_top_anchor: &Anchor,
 5769) -> Vector2F {
 5770    if *scroll_top_anchor != Anchor::min() {
 5771        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5772        scroll_position.set_y(scroll_top + scroll_position.y());
 5773    } else {
 5774        scroll_position.set_y(0.);
 5775    }
 5776    scroll_position
 5777}
 5778
 5779#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5780pub enum Event {
 5781    Activate,
 5782    BufferEdited,
 5783    Edited,
 5784    Reparsed,
 5785    Blurred,
 5786    DirtyChanged,
 5787    Saved,
 5788    TitleChanged,
 5789    SelectionsChanged { local: bool },
 5790    ScrollPositionChanged { local: bool },
 5791    Closed,
 5792}
 5793
 5794pub struct EditorFocused(pub ViewHandle<Editor>);
 5795pub struct EditorBlurred(pub ViewHandle<Editor>);
 5796pub struct EditorReleased(pub WeakViewHandle<Editor>);
 5797
 5798impl Entity for Editor {
 5799    type Event = Event;
 5800
 5801    fn release(&mut self, cx: &mut MutableAppContext) {
 5802        cx.emit_global(EditorReleased(self.handle.clone()));
 5803    }
 5804}
 5805
 5806impl View for Editor {
 5807    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 5808        let style = self.style(cx);
 5809        let font_changed = self.display_map.update(cx, |map, cx| {
 5810            map.set_font(style.text.font_id, style.text.font_size, cx)
 5811        });
 5812
 5813        if font_changed {
 5814            let handle = self.handle.clone();
 5815            cx.defer(move |cx| {
 5816                if let Some(editor) = handle.upgrade(cx) {
 5817                    editor.update(cx, |editor, cx| {
 5818                        hide_hover(editor, cx);
 5819                    })
 5820                }
 5821            });
 5822        }
 5823
 5824        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 5825    }
 5826
 5827    fn ui_name() -> &'static str {
 5828        "Editor"
 5829    }
 5830
 5831    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 5832        let focused_event = EditorFocused(cx.handle());
 5833        cx.emit_global(focused_event);
 5834        if let Some(rename) = self.pending_rename.as_ref() {
 5835            cx.focus(&rename.editor);
 5836        } else {
 5837            self.focused = true;
 5838            self.blink_cursors(self.blink_epoch, cx);
 5839            self.buffer.update(cx, |buffer, cx| {
 5840                buffer.finalize_last_transaction(cx);
 5841                if self.leader_replica_id.is_none() {
 5842                    buffer.set_active_selections(
 5843                        &self.selections.disjoint_anchors(),
 5844                        self.selections.line_mode,
 5845                        cx,
 5846                    );
 5847                }
 5848            });
 5849        }
 5850    }
 5851
 5852    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 5853        let blurred_event = EditorBlurred(cx.handle());
 5854        cx.emit_global(blurred_event);
 5855        self.focused = false;
 5856        self.buffer
 5857            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 5858        self.hide_context_menu(cx);
 5859        hide_hover(self, cx);
 5860        cx.emit(Event::Blurred);
 5861        cx.notify();
 5862
 5863        if cx.global::<Settings>().autosave == Autosave::OnFocusChange {
 5864            self.autosave(cx).detach_and_log_err(cx);
 5865        }
 5866    }
 5867
 5868    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 5869        let mut context = Self::default_keymap_context();
 5870        let mode = match self.mode {
 5871            EditorMode::SingleLine => "single_line",
 5872            EditorMode::AutoHeight { .. } => "auto_height",
 5873            EditorMode::Full => "full",
 5874        };
 5875        context.map.insert("mode".into(), mode.into());
 5876        if self.pending_rename.is_some() {
 5877            context.set.insert("renaming".into());
 5878        }
 5879        match self.context_menu.as_ref() {
 5880            Some(ContextMenu::Completions(_)) => {
 5881                context.set.insert("showing_completions".into());
 5882            }
 5883            Some(ContextMenu::CodeActions(_)) => {
 5884                context.set.insert("showing_code_actions".into());
 5885            }
 5886            None => {}
 5887        }
 5888
 5889        for layer in self.keymap_context_layers.values() {
 5890            context.extend(layer);
 5891        }
 5892
 5893        context
 5894    }
 5895}
 5896
 5897fn build_style(
 5898    settings: &Settings,
 5899    get_field_editor_theme: Option<GetFieldEditorTheme>,
 5900    override_text_style: Option<&OverrideTextStyle>,
 5901    cx: &AppContext,
 5902) -> EditorStyle {
 5903    let font_cache = cx.font_cache();
 5904
 5905    let mut theme = settings.theme.editor.clone();
 5906    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 5907        let field_editor_theme = get_field_editor_theme(&settings.theme);
 5908        theme.text_color = field_editor_theme.text.color;
 5909        theme.selection = field_editor_theme.selection;
 5910        theme.background = field_editor_theme
 5911            .container
 5912            .background_color
 5913            .unwrap_or_default();
 5914        EditorStyle {
 5915            text: field_editor_theme.text,
 5916            placeholder_text: field_editor_theme.placeholder_text,
 5917            theme,
 5918        }
 5919    } else {
 5920        let font_family_id = settings.buffer_font_family;
 5921        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 5922        let font_properties = Default::default();
 5923        let font_id = font_cache
 5924            .select_font(font_family_id, &font_properties)
 5925            .unwrap();
 5926        let font_size = settings.buffer_font_size;
 5927        EditorStyle {
 5928            text: TextStyle {
 5929                color: settings.theme.editor.text_color,
 5930                font_family_name,
 5931                font_family_id,
 5932                font_id,
 5933                font_size,
 5934                font_properties,
 5935                underline: Default::default(),
 5936            },
 5937            placeholder_text: None,
 5938            theme,
 5939        }
 5940    };
 5941
 5942    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 5943        if let Some(highlighted) = style
 5944            .text
 5945            .clone()
 5946            .highlight(highlight_style, font_cache)
 5947            .log_err()
 5948        {
 5949            style.text = highlighted;
 5950        }
 5951    }
 5952
 5953    style
 5954}
 5955
 5956trait SelectionExt {
 5957    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 5958    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 5959    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 5960    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 5961        -> Range<u32>;
 5962}
 5963
 5964impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 5965    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 5966        let start = self.start.to_point(buffer);
 5967        let end = self.end.to_point(buffer);
 5968        if self.reversed {
 5969            end..start
 5970        } else {
 5971            start..end
 5972        }
 5973    }
 5974
 5975    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 5976        let start = self.start.to_offset(buffer);
 5977        let end = self.end.to_offset(buffer);
 5978        if self.reversed {
 5979            end..start
 5980        } else {
 5981            start..end
 5982        }
 5983    }
 5984
 5985    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 5986        let start = self
 5987            .start
 5988            .to_point(&map.buffer_snapshot)
 5989            .to_display_point(map);
 5990        let end = self
 5991            .end
 5992            .to_point(&map.buffer_snapshot)
 5993            .to_display_point(map);
 5994        if self.reversed {
 5995            end..start
 5996        } else {
 5997            start..end
 5998        }
 5999    }
 6000
 6001    fn spanned_rows(
 6002        &self,
 6003        include_end_if_at_line_start: bool,
 6004        map: &DisplaySnapshot,
 6005    ) -> Range<u32> {
 6006        let start = self.start.to_point(&map.buffer_snapshot);
 6007        let mut end = self.end.to_point(&map.buffer_snapshot);
 6008        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6009            end.row -= 1;
 6010        }
 6011
 6012        let buffer_start = map.prev_line_boundary(start).0;
 6013        let buffer_end = map.next_line_boundary(end).0;
 6014        buffer_start.row..buffer_end.row + 1
 6015    }
 6016}
 6017
 6018impl<T: InvalidationRegion> InvalidationStack<T> {
 6019    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6020    where
 6021        S: Clone + ToOffset,
 6022    {
 6023        while let Some(region) = self.last() {
 6024            let all_selections_inside_invalidation_ranges =
 6025                if selections.len() == region.ranges().len() {
 6026                    selections
 6027                        .iter()
 6028                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6029                        .all(|(selection, invalidation_range)| {
 6030                            let head = selection.head().to_offset(&buffer);
 6031                            invalidation_range.start <= head && invalidation_range.end >= head
 6032                        })
 6033                } else {
 6034                    false
 6035                };
 6036
 6037            if all_selections_inside_invalidation_ranges {
 6038                break;
 6039            } else {
 6040                self.pop();
 6041            }
 6042        }
 6043    }
 6044}
 6045
 6046impl<T> Default for InvalidationStack<T> {
 6047    fn default() -> Self {
 6048        Self(Default::default())
 6049    }
 6050}
 6051
 6052impl<T> Deref for InvalidationStack<T> {
 6053    type Target = Vec<T>;
 6054
 6055    fn deref(&self) -> &Self::Target {
 6056        &self.0
 6057    }
 6058}
 6059
 6060impl<T> DerefMut for InvalidationStack<T> {
 6061    fn deref_mut(&mut self) -> &mut Self::Target {
 6062        &mut self.0
 6063    }
 6064}
 6065
 6066impl InvalidationRegion for BracketPairState {
 6067    fn ranges(&self) -> &[Range<Anchor>] {
 6068        &self.ranges
 6069    }
 6070}
 6071
 6072impl InvalidationRegion for SnippetState {
 6073    fn ranges(&self) -> &[Range<Anchor>] {
 6074        &self.ranges[self.active_index]
 6075    }
 6076}
 6077
 6078impl Deref for EditorStyle {
 6079    type Target = theme::Editor;
 6080
 6081    fn deref(&self) -> &Self::Target {
 6082        &self.theme
 6083    }
 6084}
 6085
 6086pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6087    let mut highlighted_lines = Vec::new();
 6088    for line in diagnostic.message.lines() {
 6089        highlighted_lines.push(highlight_diagnostic_message(line));
 6090    }
 6091
 6092    Arc::new(move |cx: &mut BlockContext| {
 6093        let settings = cx.global::<Settings>();
 6094        let theme = &settings.theme.editor;
 6095        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6096        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6097        Flex::column()
 6098            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6099                Label::new(
 6100                    line.clone(),
 6101                    style.message.clone().with_font_size(font_size),
 6102                )
 6103                .with_highlights(highlights.clone())
 6104                .contained()
 6105                .with_margin_left(cx.anchor_x)
 6106                .boxed()
 6107            }))
 6108            .aligned()
 6109            .left()
 6110            .boxed()
 6111    })
 6112}
 6113
 6114pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6115    let mut message_without_backticks = String::new();
 6116    let mut prev_offset = 0;
 6117    let mut inside_block = false;
 6118    let mut highlights = Vec::new();
 6119    for (match_ix, (offset, _)) in message
 6120        .match_indices('`')
 6121        .chain([(message.len(), "")])
 6122        .enumerate()
 6123    {
 6124        message_without_backticks.push_str(&message[prev_offset..offset]);
 6125        if inside_block {
 6126            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6127        }
 6128
 6129        inside_block = !inside_block;
 6130        prev_offset = offset + 1;
 6131    }
 6132
 6133    (message_without_backticks, highlights)
 6134}
 6135
 6136pub fn diagnostic_style(
 6137    severity: DiagnosticSeverity,
 6138    valid: bool,
 6139    theme: &theme::Editor,
 6140) -> DiagnosticStyle {
 6141    match (severity, valid) {
 6142        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6143        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6144        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6145        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6146        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6147        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6148        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6149        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6150        _ => theme.invalid_hint_diagnostic.clone(),
 6151    }
 6152}
 6153
 6154pub fn combine_syntax_and_fuzzy_match_highlights(
 6155    text: &str,
 6156    default_style: HighlightStyle,
 6157    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6158    match_indices: &[usize],
 6159) -> Vec<(Range<usize>, HighlightStyle)> {
 6160    let mut result = Vec::new();
 6161    let mut match_indices = match_indices.iter().copied().peekable();
 6162
 6163    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6164    {
 6165        syntax_highlight.weight = None;
 6166
 6167        // Add highlights for any fuzzy match characters before the next
 6168        // syntax highlight range.
 6169        while let Some(&match_index) = match_indices.peek() {
 6170            if match_index >= range.start {
 6171                break;
 6172            }
 6173            match_indices.next();
 6174            let end_index = char_ix_after(match_index, text);
 6175            let mut match_style = default_style;
 6176            match_style.weight = Some(fonts::Weight::BOLD);
 6177            result.push((match_index..end_index, match_style));
 6178        }
 6179
 6180        if range.start == usize::MAX {
 6181            break;
 6182        }
 6183
 6184        // Add highlights for any fuzzy match characters within the
 6185        // syntax highlight range.
 6186        let mut offset = range.start;
 6187        while let Some(&match_index) = match_indices.peek() {
 6188            if match_index >= range.end {
 6189                break;
 6190            }
 6191
 6192            match_indices.next();
 6193            if match_index > offset {
 6194                result.push((offset..match_index, syntax_highlight));
 6195            }
 6196
 6197            let mut end_index = char_ix_after(match_index, text);
 6198            while let Some(&next_match_index) = match_indices.peek() {
 6199                if next_match_index == end_index && next_match_index < range.end {
 6200                    end_index = char_ix_after(next_match_index, text);
 6201                    match_indices.next();
 6202                } else {
 6203                    break;
 6204                }
 6205            }
 6206
 6207            let mut match_style = syntax_highlight;
 6208            match_style.weight = Some(fonts::Weight::BOLD);
 6209            result.push((match_index..end_index, match_style));
 6210            offset = end_index;
 6211        }
 6212
 6213        if offset < range.end {
 6214            result.push((offset..range.end, syntax_highlight));
 6215        }
 6216    }
 6217
 6218    fn char_ix_after(ix: usize, text: &str) -> usize {
 6219        ix + text[ix..].chars().next().unwrap().len_utf8()
 6220    }
 6221
 6222    result
 6223}
 6224
 6225pub fn styled_runs_for_code_label<'a>(
 6226    label: &'a CodeLabel,
 6227    syntax_theme: &'a theme::SyntaxTheme,
 6228) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6229    let fade_out = HighlightStyle {
 6230        fade_out: Some(0.35),
 6231        ..Default::default()
 6232    };
 6233
 6234    let mut prev_end = label.filter_range.end;
 6235    label
 6236        .runs
 6237        .iter()
 6238        .enumerate()
 6239        .flat_map(move |(ix, (range, highlight_id))| {
 6240            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6241                style
 6242            } else {
 6243                return Default::default();
 6244            };
 6245            let mut muted_style = style.clone();
 6246            muted_style.highlight(fade_out);
 6247
 6248            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6249            if range.start >= label.filter_range.end {
 6250                if range.start > prev_end {
 6251                    runs.push((prev_end..range.start, fade_out));
 6252                }
 6253                runs.push((range.clone(), muted_style));
 6254            } else if range.end <= label.filter_range.end {
 6255                runs.push((range.clone(), style));
 6256            } else {
 6257                runs.push((range.start..label.filter_range.end, style));
 6258                runs.push((label.filter_range.end..range.end, muted_style));
 6259            }
 6260            prev_end = cmp::max(prev_end, range.end);
 6261
 6262            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6263                runs.push((prev_end..label.text.len(), fade_out));
 6264            }
 6265
 6266            runs
 6267        })
 6268}
 6269
 6270#[cfg(test)]
 6271mod tests {
 6272    use crate::test::{
 6273        assert_text_with_selections, build_editor, select_ranges, EditorTestContext,
 6274    };
 6275
 6276    use super::*;
 6277    use futures::StreamExt;
 6278    use gpui::{
 6279        geometry::rect::RectF,
 6280        platform::{WindowBounds, WindowOptions},
 6281    };
 6282    use indoc::indoc;
 6283    use language::{FakeLspAdapter, LanguageConfig};
 6284    use lsp::FakeLanguageServer;
 6285    use project::FakeFs;
 6286    use settings::LanguageSettings;
 6287    use std::{cell::RefCell, rc::Rc, time::Instant};
 6288    use text::Point;
 6289    use unindent::Unindent;
 6290    use util::{
 6291        assert_set_eq,
 6292        test::{marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text},
 6293    };
 6294    use workspace::{FollowableItem, ItemHandle};
 6295
 6296    #[gpui::test]
 6297    fn test_edit_events(cx: &mut MutableAppContext) {
 6298        cx.set_global(Settings::test(cx));
 6299        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6300
 6301        let events = Rc::new(RefCell::new(Vec::new()));
 6302        let (_, editor1) = cx.add_window(Default::default(), {
 6303            let events = events.clone();
 6304            |cx| {
 6305                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6306                    if matches!(
 6307                        event,
 6308                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6309                    ) {
 6310                        events.borrow_mut().push(("editor1", *event));
 6311                    }
 6312                })
 6313                .detach();
 6314                Editor::for_buffer(buffer.clone(), None, cx)
 6315            }
 6316        });
 6317        let (_, editor2) = cx.add_window(Default::default(), {
 6318            let events = events.clone();
 6319            |cx| {
 6320                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6321                    if matches!(
 6322                        event,
 6323                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6324                    ) {
 6325                        events.borrow_mut().push(("editor2", *event));
 6326                    }
 6327                })
 6328                .detach();
 6329                Editor::for_buffer(buffer.clone(), None, cx)
 6330            }
 6331        });
 6332        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6333
 6334        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6335        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6336        assert_eq!(
 6337            mem::take(&mut *events.borrow_mut()),
 6338            [
 6339                ("editor1", Event::Edited),
 6340                ("editor1", Event::BufferEdited),
 6341                ("editor2", Event::BufferEdited),
 6342                ("editor1", Event::DirtyChanged),
 6343                ("editor2", Event::DirtyChanged)
 6344            ]
 6345        );
 6346
 6347        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6348        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6349        assert_eq!(
 6350            mem::take(&mut *events.borrow_mut()),
 6351            [
 6352                ("editor2", Event::Edited),
 6353                ("editor1", Event::BufferEdited),
 6354                ("editor2", Event::BufferEdited),
 6355            ]
 6356        );
 6357
 6358        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6359        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6360        assert_eq!(
 6361            mem::take(&mut *events.borrow_mut()),
 6362            [
 6363                ("editor1", Event::Edited),
 6364                ("editor1", Event::BufferEdited),
 6365                ("editor2", Event::BufferEdited),
 6366                ("editor1", Event::DirtyChanged),
 6367                ("editor2", Event::DirtyChanged),
 6368            ]
 6369        );
 6370
 6371        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6372        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6373        assert_eq!(
 6374            mem::take(&mut *events.borrow_mut()),
 6375            [
 6376                ("editor1", Event::Edited),
 6377                ("editor1", Event::BufferEdited),
 6378                ("editor2", Event::BufferEdited),
 6379                ("editor1", Event::DirtyChanged),
 6380                ("editor2", Event::DirtyChanged),
 6381            ]
 6382        );
 6383
 6384        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6385        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6386        assert_eq!(
 6387            mem::take(&mut *events.borrow_mut()),
 6388            [
 6389                ("editor2", Event::Edited),
 6390                ("editor1", Event::BufferEdited),
 6391                ("editor2", Event::BufferEdited),
 6392                ("editor1", Event::DirtyChanged),
 6393                ("editor2", Event::DirtyChanged),
 6394            ]
 6395        );
 6396
 6397        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6398        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6399        assert_eq!(
 6400            mem::take(&mut *events.borrow_mut()),
 6401            [
 6402                ("editor2", Event::Edited),
 6403                ("editor1", Event::BufferEdited),
 6404                ("editor2", Event::BufferEdited),
 6405                ("editor1", Event::DirtyChanged),
 6406                ("editor2", Event::DirtyChanged),
 6407            ]
 6408        );
 6409
 6410        // No event is emitted when the mutation is a no-op.
 6411        editor2.update(cx, |editor, cx| {
 6412            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6413
 6414            editor.backspace(&Backspace, cx);
 6415        });
 6416        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6417    }
 6418
 6419    #[gpui::test]
 6420    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6421        cx.set_global(Settings::test(cx));
 6422        let mut now = Instant::now();
 6423        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6424        let group_interval = buffer.read(cx).transaction_group_interval();
 6425        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6426        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6427
 6428        editor.update(cx, |editor, cx| {
 6429            editor.start_transaction_at(now, cx);
 6430            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6431
 6432            editor.insert("cd", cx);
 6433            editor.end_transaction_at(now, cx);
 6434            assert_eq!(editor.text(cx), "12cd56");
 6435            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6436
 6437            editor.start_transaction_at(now, cx);
 6438            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6439            editor.insert("e", cx);
 6440            editor.end_transaction_at(now, cx);
 6441            assert_eq!(editor.text(cx), "12cde6");
 6442            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6443
 6444            now += group_interval + Duration::from_millis(1);
 6445            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6446
 6447            // Simulate an edit in another editor
 6448            buffer.update(cx, |buffer, cx| {
 6449                buffer.start_transaction_at(now, cx);
 6450                buffer.edit([(0..1, "a")], cx);
 6451                buffer.edit([(1..1, "b")], cx);
 6452                buffer.end_transaction_at(now, cx);
 6453            });
 6454
 6455            assert_eq!(editor.text(cx), "ab2cde6");
 6456            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6457
 6458            // Last transaction happened past the group interval in a different editor.
 6459            // Undo it individually and don't restore selections.
 6460            editor.undo(&Undo, cx);
 6461            assert_eq!(editor.text(cx), "12cde6");
 6462            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6463
 6464            // First two transactions happened within the group interval in this editor.
 6465            // Undo them together and restore selections.
 6466            editor.undo(&Undo, cx);
 6467            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6468            assert_eq!(editor.text(cx), "123456");
 6469            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6470
 6471            // Redo the first two transactions together.
 6472            editor.redo(&Redo, cx);
 6473            assert_eq!(editor.text(cx), "12cde6");
 6474            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6475
 6476            // Redo the last transaction on its own.
 6477            editor.redo(&Redo, cx);
 6478            assert_eq!(editor.text(cx), "ab2cde6");
 6479            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6480
 6481            // Test empty transactions.
 6482            editor.start_transaction_at(now, cx);
 6483            editor.end_transaction_at(now, cx);
 6484            editor.undo(&Undo, cx);
 6485            assert_eq!(editor.text(cx), "12cde6");
 6486        });
 6487    }
 6488
 6489    #[gpui::test]
 6490    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6491        cx.set_global(Settings::test(cx));
 6492
 6493        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6494        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6495        editor.update(cx, |view, cx| {
 6496            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6497        });
 6498        assert_eq!(
 6499            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6500            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6501        );
 6502
 6503        editor.update(cx, |view, cx| {
 6504            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6505        });
 6506
 6507        assert_eq!(
 6508            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6509            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6510        );
 6511
 6512        editor.update(cx, |view, cx| {
 6513            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6514        });
 6515
 6516        assert_eq!(
 6517            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6518            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6519        );
 6520
 6521        editor.update(cx, |view, cx| {
 6522            view.end_selection(cx);
 6523            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6524        });
 6525
 6526        assert_eq!(
 6527            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6528            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6529        );
 6530
 6531        editor.update(cx, |view, cx| {
 6532            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6533            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6534        });
 6535
 6536        assert_eq!(
 6537            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6538            [
 6539                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6540                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6541            ]
 6542        );
 6543
 6544        editor.update(cx, |view, cx| {
 6545            view.end_selection(cx);
 6546        });
 6547
 6548        assert_eq!(
 6549            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6550            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6551        );
 6552    }
 6553
 6554    #[gpui::test]
 6555    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6556        cx.set_global(Settings::test(cx));
 6557        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6558        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6559
 6560        view.update(cx, |view, cx| {
 6561            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6562            assert_eq!(
 6563                view.selections.display_ranges(cx),
 6564                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6565            );
 6566        });
 6567
 6568        view.update(cx, |view, cx| {
 6569            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6570            assert_eq!(
 6571                view.selections.display_ranges(cx),
 6572                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6573            );
 6574        });
 6575
 6576        view.update(cx, |view, cx| {
 6577            view.cancel(&Cancel, cx);
 6578            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6579            assert_eq!(
 6580                view.selections.display_ranges(cx),
 6581                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6582            );
 6583        });
 6584    }
 6585
 6586    #[gpui::test]
 6587    fn test_clone(cx: &mut gpui::MutableAppContext) {
 6588        let (text, selection_ranges) = marked_text_ranges(indoc! {"
 6589            one
 6590            two
 6591            three[]
 6592            four
 6593            five[]
 6594        "});
 6595        cx.set_global(Settings::test(cx));
 6596        let buffer = MultiBuffer::build_simple(&text, cx);
 6597
 6598        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6599
 6600        editor.update(cx, |editor, cx| {
 6601            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 6602            editor.fold_ranges(
 6603                [
 6604                    Point::new(1, 0)..Point::new(2, 0),
 6605                    Point::new(3, 0)..Point::new(4, 0),
 6606                ],
 6607                cx,
 6608            );
 6609        });
 6610
 6611        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 6612            cx.add_window(Default::default(), |cx| editor.clone(cx))
 6613        });
 6614
 6615        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 6616        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 6617
 6618        assert_eq!(
 6619            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 6620            editor.update(cx, |e, cx| e.display_text(cx))
 6621        );
 6622        assert_eq!(
 6623            cloned_snapshot
 6624                .folds_in_range(0..text.len())
 6625                .collect::<Vec<_>>(),
 6626            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 6627        );
 6628        assert_set_eq!(
 6629            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 6630            editor.read(cx).selections.ranges(cx)
 6631        );
 6632        assert_set_eq!(
 6633            cloned_editor.update(cx, |e, cx| dbg!(e.selections.display_ranges(cx))),
 6634            editor.update(cx, |e, cx| dbg!(e.selections.display_ranges(cx)))
 6635        );
 6636    }
 6637
 6638    #[gpui::test]
 6639    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6640        cx.set_global(Settings::test(cx));
 6641        use workspace::Item;
 6642        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6643        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6644
 6645        cx.add_window(Default::default(), |cx| {
 6646            let mut editor = build_editor(buffer.clone(), cx);
 6647            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6648
 6649            // Move the cursor a small distance.
 6650            // Nothing is added to the navigation history.
 6651            editor.change_selections(None, cx, |s| {
 6652                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 6653            });
 6654            editor.change_selections(None, cx, |s| {
 6655                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 6656            });
 6657            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6658
 6659            // Move the cursor a large distance.
 6660            // The history can jump back to the previous position.
 6661            editor.change_selections(None, cx, |s| {
 6662                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 6663            });
 6664            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6665            editor.navigate(nav_entry.data.unwrap(), cx);
 6666            assert_eq!(nav_entry.item.id(), cx.view_id());
 6667            assert_eq!(
 6668                editor.selections.display_ranges(cx),
 6669                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6670            );
 6671            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6672
 6673            // Move the cursor a small distance via the mouse.
 6674            // Nothing is added to the navigation history.
 6675            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6676            editor.end_selection(cx);
 6677            assert_eq!(
 6678                editor.selections.display_ranges(cx),
 6679                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6680            );
 6681            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6682
 6683            // Move the cursor a large distance via the mouse.
 6684            // The history can jump back to the previous position.
 6685            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6686            editor.end_selection(cx);
 6687            assert_eq!(
 6688                editor.selections.display_ranges(cx),
 6689                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6690            );
 6691            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6692            editor.navigate(nav_entry.data.unwrap(), cx);
 6693            assert_eq!(nav_entry.item.id(), cx.view_id());
 6694            assert_eq!(
 6695                editor.selections.display_ranges(cx),
 6696                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6697            );
 6698            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6699
 6700            // Set scroll position to check later
 6701            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6702            let original_scroll_position = editor.scroll_position;
 6703            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6704
 6705            // Jump to the end of the document and adjust scroll
 6706            editor.move_to_end(&MoveToEnd, cx);
 6707            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6708            assert_ne!(editor.scroll_position, original_scroll_position);
 6709            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6710
 6711            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6712            editor.navigate(nav_entry.data.unwrap(), cx);
 6713            assert_eq!(editor.scroll_position, original_scroll_position);
 6714            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6715
 6716            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6717            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6718            invalid_anchor.text_anchor.buffer_id = Some(999);
 6719            let invalid_point = Point::new(9999, 0);
 6720            editor.navigate(
 6721                Box::new(NavigationData {
 6722                    cursor_anchor: invalid_anchor.clone(),
 6723                    cursor_position: invalid_point,
 6724                    scroll_top_anchor: invalid_anchor.clone(),
 6725                    scroll_top_row: invalid_point.row,
 6726                    scroll_position: Default::default(),
 6727                }),
 6728                cx,
 6729            );
 6730            assert_eq!(
 6731                editor.selections.display_ranges(cx),
 6732                &[editor.max_point(cx)..editor.max_point(cx)]
 6733            );
 6734            assert_eq!(
 6735                editor.scroll_position(cx),
 6736                vec2f(0., editor.max_point(cx).row() as f32)
 6737            );
 6738
 6739            editor
 6740        });
 6741    }
 6742
 6743    #[gpui::test]
 6744    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6745        cx.set_global(Settings::test(cx));
 6746        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6747        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6748
 6749        view.update(cx, |view, cx| {
 6750            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6751            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6752            view.end_selection(cx);
 6753
 6754            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6755            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6756            view.end_selection(cx);
 6757            assert_eq!(
 6758                view.selections.display_ranges(cx),
 6759                [
 6760                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6761                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6762                ]
 6763            );
 6764        });
 6765
 6766        view.update(cx, |view, cx| {
 6767            view.cancel(&Cancel, cx);
 6768            assert_eq!(
 6769                view.selections.display_ranges(cx),
 6770                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6771            );
 6772        });
 6773
 6774        view.update(cx, |view, cx| {
 6775            view.cancel(&Cancel, cx);
 6776            assert_eq!(
 6777                view.selections.display_ranges(cx),
 6778                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6779            );
 6780        });
 6781    }
 6782
 6783    #[gpui::test]
 6784    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6785        cx.set_global(Settings::test(cx));
 6786        let buffer = MultiBuffer::build_simple(
 6787            &"
 6788                impl Foo {
 6789                    // Hello!
 6790
 6791                    fn a() {
 6792                        1
 6793                    }
 6794
 6795                    fn b() {
 6796                        2
 6797                    }
 6798
 6799                    fn c() {
 6800                        3
 6801                    }
 6802                }
 6803            "
 6804            .unindent(),
 6805            cx,
 6806        );
 6807        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6808
 6809        view.update(cx, |view, cx| {
 6810            view.change_selections(None, cx, |s| {
 6811                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 6812            });
 6813            view.fold(&Fold, cx);
 6814            assert_eq!(
 6815                view.display_text(cx),
 6816                "
 6817                    impl Foo {
 6818                        // Hello!
 6819
 6820                        fn a() {
 6821                            1
 6822                        }
 6823
 6824                        fn b() {…
 6825                        }
 6826
 6827                        fn c() {…
 6828                        }
 6829                    }
 6830                "
 6831                .unindent(),
 6832            );
 6833
 6834            view.fold(&Fold, cx);
 6835            assert_eq!(
 6836                view.display_text(cx),
 6837                "
 6838                    impl Foo {…
 6839                    }
 6840                "
 6841                .unindent(),
 6842            );
 6843
 6844            view.unfold_lines(&UnfoldLines, cx);
 6845            assert_eq!(
 6846                view.display_text(cx),
 6847                "
 6848                    impl Foo {
 6849                        // Hello!
 6850
 6851                        fn a() {
 6852                            1
 6853                        }
 6854
 6855                        fn b() {…
 6856                        }
 6857
 6858                        fn c() {…
 6859                        }
 6860                    }
 6861                "
 6862                .unindent(),
 6863            );
 6864
 6865            view.unfold_lines(&UnfoldLines, cx);
 6866            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6867        });
 6868    }
 6869
 6870    #[gpui::test]
 6871    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6872        cx.set_global(Settings::test(cx));
 6873        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6874        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6875
 6876        buffer.update(cx, |buffer, cx| {
 6877            buffer.edit(
 6878                vec![
 6879                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 6880                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 6881                ],
 6882                cx,
 6883            );
 6884        });
 6885
 6886        view.update(cx, |view, cx| {
 6887            assert_eq!(
 6888                view.selections.display_ranges(cx),
 6889                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6890            );
 6891
 6892            view.move_down(&MoveDown, cx);
 6893            assert_eq!(
 6894                view.selections.display_ranges(cx),
 6895                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6896            );
 6897
 6898            view.move_right(&MoveRight, cx);
 6899            assert_eq!(
 6900                view.selections.display_ranges(cx),
 6901                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6902            );
 6903
 6904            view.move_left(&MoveLeft, cx);
 6905            assert_eq!(
 6906                view.selections.display_ranges(cx),
 6907                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6908            );
 6909
 6910            view.move_up(&MoveUp, cx);
 6911            assert_eq!(
 6912                view.selections.display_ranges(cx),
 6913                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6914            );
 6915
 6916            view.move_to_end(&MoveToEnd, cx);
 6917            assert_eq!(
 6918                view.selections.display_ranges(cx),
 6919                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 6920            );
 6921
 6922            view.move_to_beginning(&MoveToBeginning, cx);
 6923            assert_eq!(
 6924                view.selections.display_ranges(cx),
 6925                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6926            );
 6927
 6928            view.change_selections(None, cx, |s| {
 6929                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 6930            });
 6931            view.select_to_beginning(&SelectToBeginning, cx);
 6932            assert_eq!(
 6933                view.selections.display_ranges(cx),
 6934                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 6935            );
 6936
 6937            view.select_to_end(&SelectToEnd, cx);
 6938            assert_eq!(
 6939                view.selections.display_ranges(cx),
 6940                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 6941            );
 6942        });
 6943    }
 6944
 6945    #[gpui::test]
 6946    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 6947        cx.set_global(Settings::test(cx));
 6948        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 6949        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6950
 6951        assert_eq!('ⓐ'.len_utf8(), 3);
 6952        assert_eq!('α'.len_utf8(), 2);
 6953
 6954        view.update(cx, |view, cx| {
 6955            view.fold_ranges(
 6956                vec![
 6957                    Point::new(0, 6)..Point::new(0, 12),
 6958                    Point::new(1, 2)..Point::new(1, 4),
 6959                    Point::new(2, 4)..Point::new(2, 8),
 6960                ],
 6961                cx,
 6962            );
 6963            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 6964
 6965            view.move_right(&MoveRight, cx);
 6966            assert_eq!(
 6967                view.selections.display_ranges(cx),
 6968                &[empty_range(0, "".len())]
 6969            );
 6970            view.move_right(&MoveRight, cx);
 6971            assert_eq!(
 6972                view.selections.display_ranges(cx),
 6973                &[empty_range(0, "ⓐⓑ".len())]
 6974            );
 6975            view.move_right(&MoveRight, cx);
 6976            assert_eq!(
 6977                view.selections.display_ranges(cx),
 6978                &[empty_range(0, "ⓐⓑ…".len())]
 6979            );
 6980
 6981            view.move_down(&MoveDown, cx);
 6982            assert_eq!(
 6983                view.selections.display_ranges(cx),
 6984                &[empty_range(1, "ab…".len())]
 6985            );
 6986            view.move_left(&MoveLeft, cx);
 6987            assert_eq!(
 6988                view.selections.display_ranges(cx),
 6989                &[empty_range(1, "ab".len())]
 6990            );
 6991            view.move_left(&MoveLeft, cx);
 6992            assert_eq!(
 6993                view.selections.display_ranges(cx),
 6994                &[empty_range(1, "a".len())]
 6995            );
 6996
 6997            view.move_down(&MoveDown, cx);
 6998            assert_eq!(
 6999                view.selections.display_ranges(cx),
 7000                &[empty_range(2, "α".len())]
 7001            );
 7002            view.move_right(&MoveRight, cx);
 7003            assert_eq!(
 7004                view.selections.display_ranges(cx),
 7005                &[empty_range(2, "αβ".len())]
 7006            );
 7007            view.move_right(&MoveRight, cx);
 7008            assert_eq!(
 7009                view.selections.display_ranges(cx),
 7010                &[empty_range(2, "αβ…".len())]
 7011            );
 7012            view.move_right(&MoveRight, cx);
 7013            assert_eq!(
 7014                view.selections.display_ranges(cx),
 7015                &[empty_range(2, "αβ…ε".len())]
 7016            );
 7017
 7018            view.move_up(&MoveUp, cx);
 7019            assert_eq!(
 7020                view.selections.display_ranges(cx),
 7021                &[empty_range(1, "ab…e".len())]
 7022            );
 7023            view.move_up(&MoveUp, cx);
 7024            assert_eq!(
 7025                view.selections.display_ranges(cx),
 7026                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7027            );
 7028            view.move_left(&MoveLeft, cx);
 7029            assert_eq!(
 7030                view.selections.display_ranges(cx),
 7031                &[empty_range(0, "ⓐⓑ…".len())]
 7032            );
 7033            view.move_left(&MoveLeft, cx);
 7034            assert_eq!(
 7035                view.selections.display_ranges(cx),
 7036                &[empty_range(0, "ⓐⓑ".len())]
 7037            );
 7038            view.move_left(&MoveLeft, cx);
 7039            assert_eq!(
 7040                view.selections.display_ranges(cx),
 7041                &[empty_range(0, "".len())]
 7042            );
 7043        });
 7044    }
 7045
 7046    #[gpui::test]
 7047    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7048        cx.set_global(Settings::test(cx));
 7049        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7050        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7051        view.update(cx, |view, cx| {
 7052            view.change_selections(None, cx, |s| {
 7053                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7054            });
 7055            view.move_down(&MoveDown, cx);
 7056            assert_eq!(
 7057                view.selections.display_ranges(cx),
 7058                &[empty_range(1, "abcd".len())]
 7059            );
 7060
 7061            view.move_down(&MoveDown, cx);
 7062            assert_eq!(
 7063                view.selections.display_ranges(cx),
 7064                &[empty_range(2, "αβγ".len())]
 7065            );
 7066
 7067            view.move_down(&MoveDown, cx);
 7068            assert_eq!(
 7069                view.selections.display_ranges(cx),
 7070                &[empty_range(3, "abcd".len())]
 7071            );
 7072
 7073            view.move_down(&MoveDown, cx);
 7074            assert_eq!(
 7075                view.selections.display_ranges(cx),
 7076                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7077            );
 7078
 7079            view.move_up(&MoveUp, cx);
 7080            assert_eq!(
 7081                view.selections.display_ranges(cx),
 7082                &[empty_range(3, "abcd".len())]
 7083            );
 7084
 7085            view.move_up(&MoveUp, cx);
 7086            assert_eq!(
 7087                view.selections.display_ranges(cx),
 7088                &[empty_range(2, "αβγ".len())]
 7089            );
 7090        });
 7091    }
 7092
 7093    #[gpui::test]
 7094    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7095        cx.set_global(Settings::test(cx));
 7096        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7097        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7098        view.update(cx, |view, cx| {
 7099            view.change_selections(None, cx, |s| {
 7100                s.select_display_ranges([
 7101                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7102                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7103                ]);
 7104            });
 7105        });
 7106
 7107        view.update(cx, |view, cx| {
 7108            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7109            assert_eq!(
 7110                view.selections.display_ranges(cx),
 7111                &[
 7112                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7113                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7114                ]
 7115            );
 7116        });
 7117
 7118        view.update(cx, |view, cx| {
 7119            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7120            assert_eq!(
 7121                view.selections.display_ranges(cx),
 7122                &[
 7123                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7124                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7125                ]
 7126            );
 7127        });
 7128
 7129        view.update(cx, |view, cx| {
 7130            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7131            assert_eq!(
 7132                view.selections.display_ranges(cx),
 7133                &[
 7134                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7135                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7136                ]
 7137            );
 7138        });
 7139
 7140        view.update(cx, |view, cx| {
 7141            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7142            assert_eq!(
 7143                view.selections.display_ranges(cx),
 7144                &[
 7145                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7146                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7147                ]
 7148            );
 7149        });
 7150
 7151        // Moving to the end of line again is a no-op.
 7152        view.update(cx, |view, cx| {
 7153            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7154            assert_eq!(
 7155                view.selections.display_ranges(cx),
 7156                &[
 7157                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7158                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7159                ]
 7160            );
 7161        });
 7162
 7163        view.update(cx, |view, cx| {
 7164            view.move_left(&MoveLeft, cx);
 7165            view.select_to_beginning_of_line(
 7166                &SelectToBeginningOfLine {
 7167                    stop_at_soft_wraps: true,
 7168                },
 7169                cx,
 7170            );
 7171            assert_eq!(
 7172                view.selections.display_ranges(cx),
 7173                &[
 7174                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7175                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7176                ]
 7177            );
 7178        });
 7179
 7180        view.update(cx, |view, cx| {
 7181            view.select_to_beginning_of_line(
 7182                &SelectToBeginningOfLine {
 7183                    stop_at_soft_wraps: true,
 7184                },
 7185                cx,
 7186            );
 7187            assert_eq!(
 7188                view.selections.display_ranges(cx),
 7189                &[
 7190                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7191                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7192                ]
 7193            );
 7194        });
 7195
 7196        view.update(cx, |view, cx| {
 7197            view.select_to_beginning_of_line(
 7198                &SelectToBeginningOfLine {
 7199                    stop_at_soft_wraps: true,
 7200                },
 7201                cx,
 7202            );
 7203            assert_eq!(
 7204                view.selections.display_ranges(cx),
 7205                &[
 7206                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7207                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7208                ]
 7209            );
 7210        });
 7211
 7212        view.update(cx, |view, cx| {
 7213            view.select_to_end_of_line(
 7214                &SelectToEndOfLine {
 7215                    stop_at_soft_wraps: true,
 7216                },
 7217                cx,
 7218            );
 7219            assert_eq!(
 7220                view.selections.display_ranges(cx),
 7221                &[
 7222                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7223                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7224                ]
 7225            );
 7226        });
 7227
 7228        view.update(cx, |view, cx| {
 7229            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7230            assert_eq!(view.display_text(cx), "ab\n  de");
 7231            assert_eq!(
 7232                view.selections.display_ranges(cx),
 7233                &[
 7234                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7235                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7236                ]
 7237            );
 7238        });
 7239
 7240        view.update(cx, |view, cx| {
 7241            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7242            assert_eq!(view.display_text(cx), "\n");
 7243            assert_eq!(
 7244                view.selections.display_ranges(cx),
 7245                &[
 7246                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7247                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7248                ]
 7249            );
 7250        });
 7251    }
 7252
 7253    #[gpui::test]
 7254    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7255        cx.set_global(Settings::test(cx));
 7256        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7257        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7258        view.update(cx, |view, cx| {
 7259            view.change_selections(None, cx, |s| {
 7260                s.select_display_ranges([
 7261                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7262                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7263                ])
 7264            });
 7265
 7266            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7267            assert_selection_ranges(
 7268                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7269                vec![('<', '>'), ('[', ']')],
 7270                view,
 7271                cx,
 7272            );
 7273
 7274            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7275            assert_selection_ranges(
 7276                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7277                vec![('<', '>'), ('[', ']')],
 7278                view,
 7279                cx,
 7280            );
 7281
 7282            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7283            assert_selection_ranges(
 7284                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7285                vec![('<', '>'), ('[', ']')],
 7286                view,
 7287                cx,
 7288            );
 7289
 7290            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7291            assert_selection_ranges(
 7292                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7293                vec![('<', '>'), ('[', ']')],
 7294                view,
 7295                cx,
 7296            );
 7297
 7298            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7299            assert_selection_ranges(
 7300                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7301                vec![('<', '>'), ('[', ']')],
 7302                view,
 7303                cx,
 7304            );
 7305
 7306            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7307            assert_selection_ranges(
 7308                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7309                vec![('<', '>'), ('[', ']')],
 7310                view,
 7311                cx,
 7312            );
 7313
 7314            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7315            assert_selection_ranges(
 7316                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7317                vec![('<', '>'), ('[', ']')],
 7318                view,
 7319                cx,
 7320            );
 7321
 7322            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7323            assert_selection_ranges(
 7324                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7325                vec![('<', '>'), ('[', ']')],
 7326                view,
 7327                cx,
 7328            );
 7329
 7330            view.move_right(&MoveRight, cx);
 7331            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7332            assert_selection_ranges(
 7333                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7334                vec![('<', '>'), ('[', ']')],
 7335                view,
 7336                cx,
 7337            );
 7338
 7339            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7340            assert_selection_ranges(
 7341                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7342                vec![('<', '>'), ('[', ']')],
 7343                view,
 7344                cx,
 7345            );
 7346
 7347            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7348            assert_selection_ranges(
 7349                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7350                vec![('<', '>'), ('[', ']')],
 7351                view,
 7352                cx,
 7353            );
 7354        });
 7355    }
 7356
 7357    #[gpui::test]
 7358    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7359        cx.set_global(Settings::test(cx));
 7360        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7361        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7362
 7363        view.update(cx, |view, cx| {
 7364            view.set_wrap_width(Some(140.), cx);
 7365            assert_eq!(
 7366                view.display_text(cx),
 7367                "use one::{\n    two::three::\n    four::five\n};"
 7368            );
 7369
 7370            view.change_selections(None, cx, |s| {
 7371                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7372            });
 7373
 7374            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7375            assert_eq!(
 7376                view.selections.display_ranges(cx),
 7377                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7378            );
 7379
 7380            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7381            assert_eq!(
 7382                view.selections.display_ranges(cx),
 7383                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7384            );
 7385
 7386            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7387            assert_eq!(
 7388                view.selections.display_ranges(cx),
 7389                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7390            );
 7391
 7392            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7393            assert_eq!(
 7394                view.selections.display_ranges(cx),
 7395                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7396            );
 7397
 7398            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7399            assert_eq!(
 7400                view.selections.display_ranges(cx),
 7401                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7402            );
 7403
 7404            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7405            assert_eq!(
 7406                view.selections.display_ranges(cx),
 7407                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7408            );
 7409        });
 7410    }
 7411
 7412    #[gpui::test]
 7413    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7414        cx.set_global(Settings::test(cx));
 7415        let (text, ranges) = marked_text_ranges("one [two three] four");
 7416        let buffer = MultiBuffer::build_simple(&text, cx);
 7417
 7418        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7419
 7420        editor.update(cx, |editor, cx| {
 7421            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
 7422            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7423            assert_eq!(editor.text(cx), " four");
 7424        });
 7425    }
 7426
 7427    #[gpui::test]
 7428    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7429        cx.set_global(Settings::test(cx));
 7430        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7431        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7432
 7433        view.update(cx, |view, cx| {
 7434            view.change_selections(None, cx, |s| {
 7435                s.select_display_ranges([
 7436                    // an empty selection - the preceding word fragment is deleted
 7437                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7438                    // characters selected - they are deleted
 7439                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7440                ])
 7441            });
 7442            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7443        });
 7444
 7445        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7446
 7447        view.update(cx, |view, cx| {
 7448            view.change_selections(None, cx, |s| {
 7449                s.select_display_ranges([
 7450                    // an empty selection - the following word fragment is deleted
 7451                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7452                    // characters selected - they are deleted
 7453                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7454                ])
 7455            });
 7456            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7457        });
 7458
 7459        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7460    }
 7461
 7462    #[gpui::test]
 7463    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7464        cx.set_global(Settings::test(cx));
 7465        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7466        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7467
 7468        view.update(cx, |view, cx| {
 7469            view.change_selections(None, cx, |s| {
 7470                s.select_display_ranges([
 7471                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7472                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7473                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7474                ])
 7475            });
 7476
 7477            view.newline(&Newline, cx);
 7478            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7479        });
 7480    }
 7481
 7482    #[gpui::test]
 7483    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7484        cx.set_global(Settings::test(cx));
 7485        let buffer = MultiBuffer::build_simple(
 7486            "
 7487                a
 7488                b(
 7489                    X
 7490                )
 7491                c(
 7492                    X
 7493                )
 7494            "
 7495            .unindent()
 7496            .as_str(),
 7497            cx,
 7498        );
 7499
 7500        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7501            let mut editor = build_editor(buffer.clone(), cx);
 7502            editor.change_selections(None, cx, |s| {
 7503                s.select_ranges([
 7504                    Point::new(2, 4)..Point::new(2, 5),
 7505                    Point::new(5, 4)..Point::new(5, 5),
 7506                ])
 7507            });
 7508            editor
 7509        });
 7510
 7511        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7512        buffer.update(cx, |buffer, cx| {
 7513            buffer.edit(
 7514                [
 7515                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7516                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7517                ],
 7518                cx,
 7519            );
 7520            assert_eq!(
 7521                buffer.read(cx).text(),
 7522                "
 7523                    a
 7524                    b()
 7525                    c()
 7526                "
 7527                .unindent()
 7528            );
 7529        });
 7530
 7531        editor.update(cx, |editor, cx| {
 7532            assert_eq!(
 7533                editor.selections.ranges(cx),
 7534                &[
 7535                    Point::new(1, 2)..Point::new(1, 2),
 7536                    Point::new(2, 2)..Point::new(2, 2),
 7537                ],
 7538            );
 7539
 7540            editor.newline(&Newline, cx);
 7541            assert_eq!(
 7542                editor.text(cx),
 7543                "
 7544                    a
 7545                    b(
 7546                    )
 7547                    c(
 7548                    )
 7549                "
 7550                .unindent()
 7551            );
 7552
 7553            // The selections are moved after the inserted newlines
 7554            assert_eq!(
 7555                editor.selections.ranges(cx),
 7556                &[
 7557                    Point::new(2, 0)..Point::new(2, 0),
 7558                    Point::new(4, 0)..Point::new(4, 0),
 7559                ],
 7560            );
 7561        });
 7562    }
 7563
 7564    #[gpui::test]
 7565    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7566        cx.set_global(Settings::test(cx));
 7567        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7568        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7569            let mut editor = build_editor(buffer.clone(), cx);
 7570            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 7571            editor
 7572        });
 7573
 7574        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7575        buffer.update(cx, |buffer, cx| {
 7576            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7577            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7578        });
 7579
 7580        editor.update(cx, |editor, cx| {
 7581            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 7582
 7583            editor.insert("Z", cx);
 7584            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7585
 7586            // The selections are moved after the inserted characters
 7587            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 7588        });
 7589    }
 7590
 7591    #[gpui::test]
 7592    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 7593        let mut cx = EditorTestContext::new(cx).await;
 7594
 7595        cx.set_state(indoc! {"
 7596              [one} [two}
 7597            three
 7598             four"});
 7599        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7600        cx.assert_editor_state(indoc! {"
 7601                [one} [two}
 7602            three
 7603             four"});
 7604
 7605        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7606        cx.assert_editor_state(indoc! {"
 7607            [one} [two}
 7608            three
 7609             four"});
 7610
 7611        // select across line ending
 7612        cx.set_state(indoc! {"
 7613            one two
 7614            t[hree
 7615            } four"});
 7616        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7617        cx.assert_editor_state(indoc! {"
 7618            one two
 7619                t[hree
 7620            } four"});
 7621
 7622        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7623        cx.assert_editor_state(indoc! {"
 7624            one two
 7625            t[hree
 7626            } four"});
 7627
 7628        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7629        cx.set_state(indoc! {"
 7630            one two
 7631            |three
 7632                four"});
 7633        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7634        cx.assert_editor_state(indoc! {"
 7635            one two
 7636                |three
 7637                four"});
 7638
 7639        cx.set_state(indoc! {"
 7640            one two
 7641            |    three
 7642             four"});
 7643        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7644        cx.assert_editor_state(indoc! {"
 7645            one two
 7646            |three
 7647             four"});
 7648    }
 7649
 7650    #[gpui::test]
 7651    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 7652        let mut cx = EditorTestContext::new(cx).await;
 7653        cx.update(|cx| {
 7654            cx.update_global::<Settings, _, _>(|settings, _| {
 7655                settings.language_settings.hard_tabs = Some(true);
 7656            });
 7657        });
 7658
 7659        // select two ranges on one line
 7660        cx.set_state(indoc! {"
 7661            [one} [two}
 7662            three
 7663            four"});
 7664        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7665        cx.assert_editor_state(indoc! {"
 7666            \t[one} [two}
 7667            three
 7668            four"});
 7669        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7670        cx.assert_editor_state(indoc! {"
 7671            \t\t[one} [two}
 7672            three
 7673            four"});
 7674        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7675        cx.assert_editor_state(indoc! {"
 7676            \t[one} [two}
 7677            three
 7678            four"});
 7679        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7680        cx.assert_editor_state(indoc! {"
 7681            [one} [two}
 7682            three
 7683            four"});
 7684
 7685        // select across a line ending
 7686        cx.set_state(indoc! {"
 7687            one two
 7688            t[hree
 7689            }four"});
 7690        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7691        cx.assert_editor_state(indoc! {"
 7692            one two
 7693            \tt[hree
 7694            }four"});
 7695        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7696        cx.assert_editor_state(indoc! {"
 7697            one two
 7698            \t\tt[hree
 7699            }four"});
 7700        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7701        cx.assert_editor_state(indoc! {"
 7702            one two
 7703            \tt[hree
 7704            }four"});
 7705        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7706        cx.assert_editor_state(indoc! {"
 7707            one two
 7708            t[hree
 7709            }four"});
 7710
 7711        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7712        cx.set_state(indoc! {"
 7713            one two
 7714            |three
 7715            four"});
 7716        cx.assert_editor_state(indoc! {"
 7717            one two
 7718            |three
 7719            four"});
 7720        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7721        cx.assert_editor_state(indoc! {"
 7722            one two
 7723            \t|three
 7724            four"});
 7725        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7726        cx.assert_editor_state(indoc! {"
 7727            one two
 7728            |three
 7729            four"});
 7730    }
 7731
 7732    #[gpui::test]
 7733    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7734        cx.set_global(
 7735            Settings::test(cx)
 7736                .with_language_defaults(
 7737                    "TOML",
 7738                    LanguageSettings {
 7739                        tab_size: Some(2.try_into().unwrap()),
 7740                        ..Default::default()
 7741                    },
 7742                )
 7743                .with_language_defaults(
 7744                    "Rust",
 7745                    LanguageSettings {
 7746                        tab_size: Some(4.try_into().unwrap()),
 7747                        ..Default::default()
 7748                    },
 7749                ),
 7750        );
 7751        let toml_language = Arc::new(Language::new(
 7752            LanguageConfig {
 7753                name: "TOML".into(),
 7754                ..Default::default()
 7755            },
 7756            None,
 7757        ));
 7758        let rust_language = Arc::new(Language::new(
 7759            LanguageConfig {
 7760                name: "Rust".into(),
 7761                ..Default::default()
 7762            },
 7763            None,
 7764        ));
 7765
 7766        let toml_buffer = cx
 7767            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7768        let rust_buffer = cx.add_model(|cx| {
 7769            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7770        });
 7771        let multibuffer = cx.add_model(|cx| {
 7772            let mut multibuffer = MultiBuffer::new(0);
 7773            multibuffer.push_excerpts(
 7774                toml_buffer.clone(),
 7775                [ExcerptRange {
 7776                    context: Point::new(0, 0)..Point::new(2, 0),
 7777                    primary: None,
 7778                }],
 7779                cx,
 7780            );
 7781            multibuffer.push_excerpts(
 7782                rust_buffer.clone(),
 7783                [ExcerptRange {
 7784                    context: Point::new(0, 0)..Point::new(1, 0),
 7785                    primary: None,
 7786                }],
 7787                cx,
 7788            );
 7789            multibuffer
 7790        });
 7791
 7792        cx.add_window(Default::default(), |cx| {
 7793            let mut editor = build_editor(multibuffer, cx);
 7794
 7795            assert_eq!(
 7796                editor.text(cx),
 7797                indoc! {"
 7798                    a = 1
 7799                    b = 2
 7800
 7801                    const c: usize = 3;
 7802                "}
 7803            );
 7804
 7805            select_ranges(
 7806                &mut editor,
 7807                indoc! {"
 7808                    [a] = 1
 7809                    b = 2
 7810
 7811                    [const c:] usize = 3;
 7812                "},
 7813                cx,
 7814            );
 7815
 7816            editor.tab(&Tab, cx);
 7817            assert_text_with_selections(
 7818                &mut editor,
 7819                indoc! {"
 7820                      [a] = 1
 7821                    b = 2
 7822
 7823                        [const c:] usize = 3;
 7824                "},
 7825                cx,
 7826            );
 7827            editor.tab_prev(&TabPrev, cx);
 7828            assert_text_with_selections(
 7829                &mut editor,
 7830                indoc! {"
 7831                    [a] = 1
 7832                    b = 2
 7833
 7834                    [const c:] usize = 3;
 7835                "},
 7836                cx,
 7837            );
 7838
 7839            editor
 7840        });
 7841    }
 7842
 7843    #[gpui::test]
 7844    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 7845        let mut cx = EditorTestContext::new(cx).await;
 7846        // Basic backspace
 7847        cx.set_state(indoc! {"
 7848            on|e two three
 7849            fou[r} five six
 7850            seven {eight nine
 7851            ]ten"});
 7852        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7853        cx.assert_editor_state(indoc! {"
 7854            o|e two three
 7855            fou| five six
 7856            seven |ten"});
 7857
 7858        // Test backspace inside and around indents
 7859        cx.set_state(indoc! {"
 7860            zero
 7861                |one
 7862                    |two
 7863                | | |  three
 7864            |  |  four"});
 7865        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7866        cx.assert_editor_state(indoc! {"
 7867            zero
 7868            |one
 7869                |two
 7870            |  three|  four"});
 7871
 7872        // Test backspace with line_mode set to true
 7873        cx.update_editor(|e, _| e.selections.line_mode = true);
 7874        cx.set_state(indoc! {"
 7875            The |quick |brown
 7876            fox jumps over
 7877            the lazy dog
 7878            |The qu[ick b}rown"});
 7879        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7880        cx.assert_editor_state(indoc! {"
 7881            |fox jumps over
 7882            the lazy dog|"});
 7883    }
 7884
 7885    #[gpui::test]
 7886    async fn test_delete(cx: &mut gpui::TestAppContext) {
 7887        let mut cx = EditorTestContext::new(cx).await;
 7888
 7889        cx.set_state(indoc! {"
 7890            on|e two three
 7891            fou[r} five six
 7892            seven {eight nine
 7893            ]ten"});
 7894        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 7895        cx.assert_editor_state(indoc! {"
 7896            on| two three
 7897            fou| five six
 7898            seven |ten"});
 7899
 7900        // Test backspace with line_mode set to true
 7901        cx.update_editor(|e, _| e.selections.line_mode = true);
 7902        cx.set_state(indoc! {"
 7903            The |quick |brown
 7904            fox {jum]ps over
 7905            the lazy dog
 7906            |The qu[ick b}rown"});
 7907        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7908        cx.assert_editor_state("|the lazy dog|");
 7909    }
 7910
 7911    #[gpui::test]
 7912    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7913        cx.set_global(Settings::test(cx));
 7914        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7915        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7916        view.update(cx, |view, cx| {
 7917            view.change_selections(None, cx, |s| {
 7918                s.select_display_ranges([
 7919                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7920                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7921                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7922                ])
 7923            });
 7924            view.delete_line(&DeleteLine, cx);
 7925            assert_eq!(view.display_text(cx), "ghi");
 7926            assert_eq!(
 7927                view.selections.display_ranges(cx),
 7928                vec![
 7929                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7930                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7931                ]
 7932            );
 7933        });
 7934
 7935        cx.set_global(Settings::test(cx));
 7936        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7937        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7938        view.update(cx, |view, cx| {
 7939            view.change_selections(None, cx, |s| {
 7940                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 7941            });
 7942            view.delete_line(&DeleteLine, cx);
 7943            assert_eq!(view.display_text(cx), "ghi\n");
 7944            assert_eq!(
 7945                view.selections.display_ranges(cx),
 7946                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 7947            );
 7948        });
 7949    }
 7950
 7951    #[gpui::test]
 7952    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 7953        cx.set_global(Settings::test(cx));
 7954        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7955        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7956        view.update(cx, |view, cx| {
 7957            view.change_selections(None, cx, |s| {
 7958                s.select_display_ranges([
 7959                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 7960                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7961                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7962                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7963                ])
 7964            });
 7965            view.duplicate_line(&DuplicateLine, cx);
 7966            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 7967            assert_eq!(
 7968                view.selections.display_ranges(cx),
 7969                vec![
 7970                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7971                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7972                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7973                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 7974                ]
 7975            );
 7976        });
 7977
 7978        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7979        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7980        view.update(cx, |view, cx| {
 7981            view.change_selections(None, cx, |s| {
 7982                s.select_display_ranges([
 7983                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 7984                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 7985                ])
 7986            });
 7987            view.duplicate_line(&DuplicateLine, cx);
 7988            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 7989            assert_eq!(
 7990                view.selections.display_ranges(cx),
 7991                vec![
 7992                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 7993                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 7994                ]
 7995            );
 7996        });
 7997    }
 7998
 7999    #[gpui::test]
 8000    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8001        cx.set_global(Settings::test(cx));
 8002        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8003        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8004        view.update(cx, |view, cx| {
 8005            view.fold_ranges(
 8006                vec![
 8007                    Point::new(0, 2)..Point::new(1, 2),
 8008                    Point::new(2, 3)..Point::new(4, 1),
 8009                    Point::new(7, 0)..Point::new(8, 4),
 8010                ],
 8011                cx,
 8012            );
 8013            view.change_selections(None, cx, |s| {
 8014                s.select_display_ranges([
 8015                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8016                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8017                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8018                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8019                ])
 8020            });
 8021            assert_eq!(
 8022                view.display_text(cx),
 8023                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8024            );
 8025
 8026            view.move_line_up(&MoveLineUp, cx);
 8027            assert_eq!(
 8028                view.display_text(cx),
 8029                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8030            );
 8031            assert_eq!(
 8032                view.selections.display_ranges(cx),
 8033                vec![
 8034                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8035                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8036                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8037                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8038                ]
 8039            );
 8040        });
 8041
 8042        view.update(cx, |view, cx| {
 8043            view.move_line_down(&MoveLineDown, cx);
 8044            assert_eq!(
 8045                view.display_text(cx),
 8046                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8047            );
 8048            assert_eq!(
 8049                view.selections.display_ranges(cx),
 8050                vec![
 8051                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8052                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8053                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8054                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8055                ]
 8056            );
 8057        });
 8058
 8059        view.update(cx, |view, cx| {
 8060            view.move_line_down(&MoveLineDown, cx);
 8061            assert_eq!(
 8062                view.display_text(cx),
 8063                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8064            );
 8065            assert_eq!(
 8066                view.selections.display_ranges(cx),
 8067                vec![
 8068                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8069                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8070                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8071                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8072                ]
 8073            );
 8074        });
 8075
 8076        view.update(cx, |view, cx| {
 8077            view.move_line_up(&MoveLineUp, cx);
 8078            assert_eq!(
 8079                view.display_text(cx),
 8080                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8081            );
 8082            assert_eq!(
 8083                view.selections.display_ranges(cx),
 8084                vec![
 8085                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8086                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8087                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8088                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8089                ]
 8090            );
 8091        });
 8092    }
 8093
 8094    #[gpui::test]
 8095    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8096        cx.set_global(Settings::test(cx));
 8097        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8098        let snapshot = buffer.read(cx).snapshot(cx);
 8099        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8100        editor.update(cx, |editor, cx| {
 8101            editor.insert_blocks(
 8102                [BlockProperties {
 8103                    style: BlockStyle::Fixed,
 8104                    position: snapshot.anchor_after(Point::new(2, 0)),
 8105                    disposition: BlockDisposition::Below,
 8106                    height: 1,
 8107                    render: Arc::new(|_| Empty::new().boxed()),
 8108                }],
 8109                cx,
 8110            );
 8111            editor.change_selections(None, cx, |s| {
 8112                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8113            });
 8114            editor.move_line_down(&MoveLineDown, cx);
 8115        });
 8116    }
 8117
 8118    #[gpui::test]
 8119    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8120        cx.set_global(Settings::test(cx));
 8121
 8122        cx.add_window(Default::default(), |cx| {
 8123            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8124
 8125            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8126            editor.transpose(&Default::default(), cx);
 8127            assert_eq!(editor.text(cx), "bac");
 8128            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8129
 8130            editor.transpose(&Default::default(), cx);
 8131            assert_eq!(editor.text(cx), "bca");
 8132            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8133
 8134            editor.transpose(&Default::default(), cx);
 8135            assert_eq!(editor.text(cx), "bac");
 8136            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8137
 8138            editor
 8139        })
 8140        .1;
 8141
 8142        cx.add_window(Default::default(), |cx| {
 8143            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8144
 8145            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8146            editor.transpose(&Default::default(), cx);
 8147            assert_eq!(editor.text(cx), "acb\nde");
 8148            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8149
 8150            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8151            editor.transpose(&Default::default(), cx);
 8152            assert_eq!(editor.text(cx), "acbd\ne");
 8153            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8154
 8155            editor.transpose(&Default::default(), cx);
 8156            assert_eq!(editor.text(cx), "acbde\n");
 8157            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8158
 8159            editor.transpose(&Default::default(), cx);
 8160            assert_eq!(editor.text(cx), "acbd\ne");
 8161            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8162
 8163            editor
 8164        })
 8165        .1;
 8166
 8167        cx.add_window(Default::default(), |cx| {
 8168            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8169
 8170            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8171            editor.transpose(&Default::default(), cx);
 8172            assert_eq!(editor.text(cx), "bacd\ne");
 8173            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8174
 8175            editor.transpose(&Default::default(), cx);
 8176            assert_eq!(editor.text(cx), "bcade\n");
 8177            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8178
 8179            editor.transpose(&Default::default(), cx);
 8180            assert_eq!(editor.text(cx), "bcda\ne");
 8181            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8182
 8183            editor.transpose(&Default::default(), cx);
 8184            assert_eq!(editor.text(cx), "bcade\n");
 8185            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8186
 8187            editor.transpose(&Default::default(), cx);
 8188            assert_eq!(editor.text(cx), "bcaed\n");
 8189            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8190
 8191            editor
 8192        })
 8193        .1;
 8194
 8195        cx.add_window(Default::default(), |cx| {
 8196            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8197
 8198            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8199            editor.transpose(&Default::default(), cx);
 8200            assert_eq!(editor.text(cx), "🏀🍐✋");
 8201            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8202
 8203            editor.transpose(&Default::default(), cx);
 8204            assert_eq!(editor.text(cx), "🏀✋🍐");
 8205            assert_eq!(editor.selections.ranges(cx), [11..11]);
 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
 8212        })
 8213        .1;
 8214    }
 8215
 8216    #[gpui::test]
 8217    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8218        let mut cx = EditorTestContext::new(cx).await;
 8219
 8220        cx.set_state("[one✅ }two [three }four [five }six ");
 8221        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8222        cx.assert_editor_state("|two |four |six ");
 8223
 8224        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8225        cx.set_state("two |four |six |");
 8226        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8227        cx.assert_editor_state("two one✅ |four three |six five |");
 8228
 8229        // Paste again but with only two cursors. Since the number of cursors doesn't
 8230        // match the number of slices in the clipboard, the entire clipboard text
 8231        // is pasted at each cursor.
 8232        cx.set_state("|two one✅ four three six five |");
 8233        cx.update_editor(|e, cx| {
 8234            e.handle_input(&Input("( ".into()), cx);
 8235            e.paste(&Paste, cx);
 8236            e.handle_input(&Input(") ".into()), cx);
 8237        });
 8238        cx.assert_editor_state(indoc! {"
 8239            ( one✅ 
 8240            three 
 8241            five ) |two one✅ four three six five ( one✅ 
 8242            three 
 8243            five ) |"});
 8244
 8245        // Cut with three selections, one of which is full-line.
 8246        cx.set_state(indoc! {"
 8247            1[2}3
 8248            4|567
 8249            [8}9"});
 8250        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8251        cx.assert_editor_state(indoc! {"
 8252            1|3
 8253            |9"});
 8254
 8255        // Paste with three selections, noticing how the copied selection that was full-line
 8256        // gets inserted before the second cursor.
 8257        cx.set_state(indoc! {"
 8258            1|3
 8259            9|
 8260            [o}ne"});
 8261        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8262        cx.assert_editor_state(indoc! {"
 8263            12|3
 8264            4567
 8265            9|
 8266            8|ne"});
 8267
 8268        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8269        cx.set_state(indoc! {"
 8270            The quick brown
 8271            fox ju|mps over
 8272            the lazy dog"});
 8273        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8274        cx.assert_clipboard_content(Some("fox jumps over\n"));
 8275
 8276        // Paste with three selections, noticing how the copied full-line selection is inserted
 8277        // before the empty selections but replaces the selection that is non-empty.
 8278        cx.set_state(indoc! {"
 8279            T|he quick brown
 8280            [fo}x jumps over
 8281            t|he lazy dog"});
 8282        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8283        cx.assert_editor_state(indoc! {"
 8284            fox jumps over
 8285            T|he quick brown
 8286            fox jumps over
 8287            |x jumps over
 8288            fox jumps over
 8289            t|he lazy dog"});
 8290    }
 8291
 8292    #[gpui::test]
 8293    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8294        cx.set_global(Settings::test(cx));
 8295        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8296        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8297        view.update(cx, |view, cx| {
 8298            view.select_all(&SelectAll, cx);
 8299            assert_eq!(
 8300                view.selections.display_ranges(cx),
 8301                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8302            );
 8303        });
 8304    }
 8305
 8306    #[gpui::test]
 8307    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8308        cx.set_global(Settings::test(cx));
 8309        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8310        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8311        view.update(cx, |view, cx| {
 8312            view.change_selections(None, cx, |s| {
 8313                s.select_display_ranges([
 8314                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8315                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8316                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8317                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8318                ])
 8319            });
 8320            view.select_line(&SelectLine, cx);
 8321            assert_eq!(
 8322                view.selections.display_ranges(cx),
 8323                vec![
 8324                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8325                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8326                ]
 8327            );
 8328        });
 8329
 8330        view.update(cx, |view, cx| {
 8331            view.select_line(&SelectLine, cx);
 8332            assert_eq!(
 8333                view.selections.display_ranges(cx),
 8334                vec![
 8335                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8336                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8337                ]
 8338            );
 8339        });
 8340
 8341        view.update(cx, |view, cx| {
 8342            view.select_line(&SelectLine, cx);
 8343            assert_eq!(
 8344                view.selections.display_ranges(cx),
 8345                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8346            );
 8347        });
 8348    }
 8349
 8350    #[gpui::test]
 8351    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8352        cx.set_global(Settings::test(cx));
 8353        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8354        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8355        view.update(cx, |view, cx| {
 8356            view.fold_ranges(
 8357                vec![
 8358                    Point::new(0, 2)..Point::new(1, 2),
 8359                    Point::new(2, 3)..Point::new(4, 1),
 8360                    Point::new(7, 0)..Point::new(8, 4),
 8361                ],
 8362                cx,
 8363            );
 8364            view.change_selections(None, cx, |s| {
 8365                s.select_display_ranges([
 8366                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8367                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8368                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8369                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8370                ])
 8371            });
 8372            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8373        });
 8374
 8375        view.update(cx, |view, cx| {
 8376            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8377            assert_eq!(
 8378                view.display_text(cx),
 8379                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8380            );
 8381            assert_eq!(
 8382                view.selections.display_ranges(cx),
 8383                [
 8384                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8385                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8386                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8387                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8388                ]
 8389            );
 8390        });
 8391
 8392        view.update(cx, |view, cx| {
 8393            view.change_selections(None, cx, |s| {
 8394                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 8395            });
 8396            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8397            assert_eq!(
 8398                view.display_text(cx),
 8399                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8400            );
 8401            assert_eq!(
 8402                view.selections.display_ranges(cx),
 8403                [
 8404                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8405                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8406                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8407                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8408                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8409                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8410                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8411                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8412                ]
 8413            );
 8414        });
 8415    }
 8416
 8417    #[gpui::test]
 8418    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8419        cx.set_global(Settings::test(cx));
 8420        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8421        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8422
 8423        view.update(cx, |view, cx| {
 8424            view.change_selections(None, cx, |s| {
 8425                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 8426            });
 8427        });
 8428        view.update(cx, |view, cx| {
 8429            view.add_selection_above(&AddSelectionAbove, cx);
 8430            assert_eq!(
 8431                view.selections.display_ranges(cx),
 8432                vec![
 8433                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8434                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8435                ]
 8436            );
 8437        });
 8438
 8439        view.update(cx, |view, cx| {
 8440            view.add_selection_above(&AddSelectionAbove, cx);
 8441            assert_eq!(
 8442                view.selections.display_ranges(cx),
 8443                vec![
 8444                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8445                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8446                ]
 8447            );
 8448        });
 8449
 8450        view.update(cx, |view, cx| {
 8451            view.add_selection_below(&AddSelectionBelow, cx);
 8452            assert_eq!(
 8453                view.selections.display_ranges(cx),
 8454                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8455            );
 8456
 8457            view.undo_selection(&UndoSelection, cx);
 8458            assert_eq!(
 8459                view.selections.display_ranges(cx),
 8460                vec![
 8461                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8462                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8463                ]
 8464            );
 8465
 8466            view.redo_selection(&RedoSelection, cx);
 8467            assert_eq!(
 8468                view.selections.display_ranges(cx),
 8469                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8470            );
 8471        });
 8472
 8473        view.update(cx, |view, cx| {
 8474            view.add_selection_below(&AddSelectionBelow, cx);
 8475            assert_eq!(
 8476                view.selections.display_ranges(cx),
 8477                vec![
 8478                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8479                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8480                ]
 8481            );
 8482        });
 8483
 8484        view.update(cx, |view, cx| {
 8485            view.add_selection_below(&AddSelectionBelow, cx);
 8486            assert_eq!(
 8487                view.selections.display_ranges(cx),
 8488                vec![
 8489                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8490                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8491                ]
 8492            );
 8493        });
 8494
 8495        view.update(cx, |view, cx| {
 8496            view.change_selections(None, cx, |s| {
 8497                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 8498            });
 8499        });
 8500        view.update(cx, |view, cx| {
 8501            view.add_selection_below(&AddSelectionBelow, cx);
 8502            assert_eq!(
 8503                view.selections.display_ranges(cx),
 8504                vec![
 8505                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8506                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8507                ]
 8508            );
 8509        });
 8510
 8511        view.update(cx, |view, cx| {
 8512            view.add_selection_below(&AddSelectionBelow, cx);
 8513            assert_eq!(
 8514                view.selections.display_ranges(cx),
 8515                vec![
 8516                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8517                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8518                ]
 8519            );
 8520        });
 8521
 8522        view.update(cx, |view, cx| {
 8523            view.add_selection_above(&AddSelectionAbove, cx);
 8524            assert_eq!(
 8525                view.selections.display_ranges(cx),
 8526                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8527            );
 8528        });
 8529
 8530        view.update(cx, |view, cx| {
 8531            view.add_selection_above(&AddSelectionAbove, cx);
 8532            assert_eq!(
 8533                view.selections.display_ranges(cx),
 8534                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8535            );
 8536        });
 8537
 8538        view.update(cx, |view, cx| {
 8539            view.change_selections(None, cx, |s| {
 8540                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 8541            });
 8542            view.add_selection_below(&AddSelectionBelow, cx);
 8543            assert_eq!(
 8544                view.selections.display_ranges(cx),
 8545                vec![
 8546                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8547                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8548                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8549                ]
 8550            );
 8551        });
 8552
 8553        view.update(cx, |view, cx| {
 8554            view.add_selection_below(&AddSelectionBelow, cx);
 8555            assert_eq!(
 8556                view.selections.display_ranges(cx),
 8557                vec![
 8558                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8559                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8560                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8561                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8562                ]
 8563            );
 8564        });
 8565
 8566        view.update(cx, |view, cx| {
 8567            view.add_selection_above(&AddSelectionAbove, cx);
 8568            assert_eq!(
 8569                view.selections.display_ranges(cx),
 8570                vec![
 8571                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8572                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8573                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8574                ]
 8575            );
 8576        });
 8577
 8578        view.update(cx, |view, cx| {
 8579            view.change_selections(None, cx, |s| {
 8580                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 8581            });
 8582        });
 8583        view.update(cx, |view, cx| {
 8584            view.add_selection_above(&AddSelectionAbove, cx);
 8585            assert_eq!(
 8586                view.selections.display_ranges(cx),
 8587                vec![
 8588                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8589                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8590                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8591                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8592                ]
 8593            );
 8594        });
 8595
 8596        view.update(cx, |view, cx| {
 8597            view.add_selection_below(&AddSelectionBelow, cx);
 8598            assert_eq!(
 8599                view.selections.display_ranges(cx),
 8600                vec![
 8601                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8602                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8603                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8604                ]
 8605            );
 8606        });
 8607    }
 8608
 8609    #[gpui::test]
 8610    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8611        cx.set_global(Settings::test(cx));
 8612
 8613        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8614        let buffer = MultiBuffer::build_simple(&text, cx);
 8615        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8616
 8617        view.update(cx, |view, cx| {
 8618            view.change_selections(None, cx, |s| {
 8619                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 8620            });
 8621            view.select_next(
 8622                &SelectNext {
 8623                    replace_newest: false,
 8624                },
 8625                cx,
 8626            );
 8627            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8628
 8629            view.select_next(
 8630                &SelectNext {
 8631                    replace_newest: false,
 8632                },
 8633                cx,
 8634            );
 8635            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8636
 8637            view.undo_selection(&UndoSelection, cx);
 8638            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8639
 8640            view.redo_selection(&RedoSelection, cx);
 8641            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8642
 8643            view.select_next(
 8644                &SelectNext {
 8645                    replace_newest: false,
 8646                },
 8647                cx,
 8648            );
 8649            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 8650
 8651            view.select_next(
 8652                &SelectNext {
 8653                    replace_newest: false,
 8654                },
 8655                cx,
 8656            );
 8657            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 8658        });
 8659    }
 8660
 8661    #[gpui::test]
 8662    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8663        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8664        let language = Arc::new(Language::new(
 8665            LanguageConfig::default(),
 8666            Some(tree_sitter_rust::language()),
 8667        ));
 8668
 8669        let text = r#"
 8670            use mod1::mod2::{mod3, mod4};
 8671
 8672            fn fn_1(param1: bool, param2: &str) {
 8673                let var1 = "text";
 8674            }
 8675        "#
 8676        .unindent();
 8677
 8678        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8679        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8680        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8681        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8682            .await;
 8683
 8684        view.update(cx, |view, cx| {
 8685            view.change_selections(None, cx, |s| {
 8686                s.select_display_ranges([
 8687                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8688                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8689                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8690                ]);
 8691            });
 8692            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8693        });
 8694        assert_eq!(
 8695            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 8696            &[
 8697                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8698                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8699                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8700            ]
 8701        );
 8702
 8703        view.update(cx, |view, cx| {
 8704            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8705        });
 8706        assert_eq!(
 8707            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8708            &[
 8709                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8710                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8711            ]
 8712        );
 8713
 8714        view.update(cx, |view, cx| {
 8715            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8716        });
 8717        assert_eq!(
 8718            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8719            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8720        );
 8721
 8722        // Trying to expand the selected syntax node one more time has no effect.
 8723        view.update(cx, |view, cx| {
 8724            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8725        });
 8726        assert_eq!(
 8727            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8728            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8729        );
 8730
 8731        view.update(cx, |view, cx| {
 8732            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8733        });
 8734        assert_eq!(
 8735            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8736            &[
 8737                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8738                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8739            ]
 8740        );
 8741
 8742        view.update(cx, |view, cx| {
 8743            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8744        });
 8745        assert_eq!(
 8746            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8747            &[
 8748                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8749                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8750                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8751            ]
 8752        );
 8753
 8754        view.update(cx, |view, cx| {
 8755            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8756        });
 8757        assert_eq!(
 8758            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8759            &[
 8760                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8761                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8762                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8763            ]
 8764        );
 8765
 8766        // Trying to shrink the selected syntax node one more time has no effect.
 8767        view.update(cx, |view, cx| {
 8768            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8769        });
 8770        assert_eq!(
 8771            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8772            &[
 8773                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8774                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8775                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8776            ]
 8777        );
 8778
 8779        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8780        // a fold.
 8781        view.update(cx, |view, cx| {
 8782            view.fold_ranges(
 8783                vec![
 8784                    Point::new(0, 21)..Point::new(0, 24),
 8785                    Point::new(3, 20)..Point::new(3, 22),
 8786                ],
 8787                cx,
 8788            );
 8789            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8790        });
 8791        assert_eq!(
 8792            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8793            &[
 8794                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8795                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8796                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8797            ]
 8798        );
 8799    }
 8800
 8801    #[gpui::test]
 8802    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8803        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8804        let language = Arc::new(
 8805            Language::new(
 8806                LanguageConfig {
 8807                    brackets: vec![
 8808                        BracketPair {
 8809                            start: "{".to_string(),
 8810                            end: "}".to_string(),
 8811                            close: false,
 8812                            newline: true,
 8813                        },
 8814                        BracketPair {
 8815                            start: "(".to_string(),
 8816                            end: ")".to_string(),
 8817                            close: false,
 8818                            newline: true,
 8819                        },
 8820                    ],
 8821                    ..Default::default()
 8822                },
 8823                Some(tree_sitter_rust::language()),
 8824            )
 8825            .with_indents_query(
 8826                r#"
 8827                (_ "(" ")" @end) @indent
 8828                (_ "{" "}" @end) @indent
 8829                "#,
 8830            )
 8831            .unwrap(),
 8832        );
 8833
 8834        let text = "fn a() {}";
 8835
 8836        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8837        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8838        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8839        editor
 8840            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8841            .await;
 8842
 8843        editor.update(cx, |editor, cx| {
 8844            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 8845            editor.newline(&Newline, cx);
 8846            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8847            assert_eq!(
 8848                editor.selections.ranges(cx),
 8849                &[
 8850                    Point::new(1, 4)..Point::new(1, 4),
 8851                    Point::new(3, 4)..Point::new(3, 4),
 8852                    Point::new(5, 0)..Point::new(5, 0)
 8853                ]
 8854            );
 8855        });
 8856    }
 8857
 8858    #[gpui::test]
 8859    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8860        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8861        let language = Arc::new(Language::new(
 8862            LanguageConfig {
 8863                brackets: vec![
 8864                    BracketPair {
 8865                        start: "{".to_string(),
 8866                        end: "}".to_string(),
 8867                        close: true,
 8868                        newline: true,
 8869                    },
 8870                    BracketPair {
 8871                        start: "/*".to_string(),
 8872                        end: " */".to_string(),
 8873                        close: true,
 8874                        newline: true,
 8875                    },
 8876                    BracketPair {
 8877                        start: "[".to_string(),
 8878                        end: "]".to_string(),
 8879                        close: false,
 8880                        newline: true,
 8881                    },
 8882                ],
 8883                autoclose_before: "})]".to_string(),
 8884                ..Default::default()
 8885            },
 8886            Some(tree_sitter_rust::language()),
 8887        ));
 8888
 8889        let text = r#"
 8890            a
 8891
 8892            /
 8893
 8894        "#
 8895        .unindent();
 8896
 8897        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8898        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8899        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8900        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8901            .await;
 8902
 8903        view.update(cx, |view, cx| {
 8904            view.change_selections(None, cx, |s| {
 8905                s.select_display_ranges([
 8906                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8907                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8908                ])
 8909            });
 8910
 8911            view.handle_input(&Input("{".to_string()), cx);
 8912            view.handle_input(&Input("{".to_string()), cx);
 8913            view.handle_input(&Input("{".to_string()), cx);
 8914            assert_eq!(
 8915                view.text(cx),
 8916                "
 8917                {{{}}}
 8918                {{{}}}
 8919                /
 8920
 8921                "
 8922                .unindent()
 8923            );
 8924
 8925            view.move_right(&MoveRight, cx);
 8926            view.handle_input(&Input("}".to_string()), cx);
 8927            view.handle_input(&Input("}".to_string()), cx);
 8928            view.handle_input(&Input("}".to_string()), cx);
 8929            assert_eq!(
 8930                view.text(cx),
 8931                "
 8932                {{{}}}}
 8933                {{{}}}}
 8934                /
 8935
 8936                "
 8937                .unindent()
 8938            );
 8939
 8940            view.undo(&Undo, cx);
 8941            view.handle_input(&Input("/".to_string()), cx);
 8942            view.handle_input(&Input("*".to_string()), cx);
 8943            assert_eq!(
 8944                view.text(cx),
 8945                "
 8946                /* */
 8947                /* */
 8948                /
 8949
 8950                "
 8951                .unindent()
 8952            );
 8953
 8954            view.undo(&Undo, cx);
 8955            view.change_selections(None, cx, |s| {
 8956                s.select_display_ranges([
 8957                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8958                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8959                ])
 8960            });
 8961            view.handle_input(&Input("*".to_string()), cx);
 8962            assert_eq!(
 8963                view.text(cx),
 8964                "
 8965                a
 8966
 8967                /*
 8968                *
 8969                "
 8970                .unindent()
 8971            );
 8972
 8973            // Don't autoclose if the next character isn't whitespace and isn't
 8974            // listed in the language's "autoclose_before" section.
 8975            view.finalize_last_transaction(cx);
 8976            view.change_selections(None, cx, |s| {
 8977                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 8978            });
 8979            view.handle_input(&Input("{".to_string()), cx);
 8980            assert_eq!(
 8981                view.text(cx),
 8982                "
 8983                {a
 8984
 8985                /*
 8986                *
 8987                "
 8988                .unindent()
 8989            );
 8990
 8991            view.undo(&Undo, cx);
 8992            view.change_selections(None, cx, |s| {
 8993                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 8994            });
 8995            view.handle_input(&Input("{".to_string()), cx);
 8996            assert_eq!(
 8997                view.text(cx),
 8998                "
 8999                {a}
 9000
 9001                /*
 9002                *
 9003                "
 9004                .unindent()
 9005            );
 9006            assert_eq!(
 9007                view.selections.display_ranges(cx),
 9008                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9009            );
 9010
 9011            view.undo(&Undo, cx);
 9012            view.handle_input(&Input("[".to_string()), cx);
 9013            assert_eq!(
 9014                view.text(cx),
 9015                "
 9016                [a]
 9017                
 9018                /*
 9019                *
 9020                "
 9021                .unindent()
 9022            );
 9023            assert_eq!(
 9024                view.selections.display_ranges(cx),
 9025                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9026            );
 9027
 9028            view.undo(&Undo, cx);
 9029            view.change_selections(None, cx, |s| {
 9030                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9031            });
 9032            view.handle_input(&Input("[".to_string()), cx);
 9033            assert_eq!(
 9034                view.text(cx),
 9035                "
 9036                a[
 9037                
 9038                /*
 9039                *
 9040                "
 9041                .unindent()
 9042            );
 9043            assert_eq!(
 9044                view.selections.display_ranges(cx),
 9045                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9046            );
 9047        });
 9048    }
 9049
 9050    #[gpui::test]
 9051    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9052        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9053        let language = Arc::new(Language::new(
 9054            LanguageConfig {
 9055                brackets: vec![BracketPair {
 9056                    start: "{".to_string(),
 9057                    end: "}".to_string(),
 9058                    close: true,
 9059                    newline: true,
 9060                }],
 9061                ..Default::default()
 9062            },
 9063            Some(tree_sitter_rust::language()),
 9064        ));
 9065
 9066        let text = r#"
 9067            a
 9068            b
 9069            c
 9070        "#
 9071        .unindent();
 9072
 9073        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9074        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9075        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9076        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9077            .await;
 9078
 9079        view.update(cx, |view, cx| {
 9080            view.change_selections(None, cx, |s| {
 9081                s.select_display_ranges([
 9082                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9083                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9084                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9085                ])
 9086            });
 9087
 9088            view.handle_input(&Input("{".to_string()), cx);
 9089            view.handle_input(&Input("{".to_string()), cx);
 9090            view.handle_input(&Input("{".to_string()), cx);
 9091            assert_eq!(
 9092                view.text(cx),
 9093                "
 9094                {{{a}}}
 9095                {{{b}}}
 9096                {{{c}}}
 9097                "
 9098                .unindent()
 9099            );
 9100            assert_eq!(
 9101                view.selections.display_ranges(cx),
 9102                [
 9103                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9104                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9105                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9106                ]
 9107            );
 9108
 9109            view.undo(&Undo, cx);
 9110            assert_eq!(
 9111                view.text(cx),
 9112                "
 9113                a
 9114                b
 9115                c
 9116                "
 9117                .unindent()
 9118            );
 9119            assert_eq!(
 9120                view.selections.display_ranges(cx),
 9121                [
 9122                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9123                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9124                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9125                ]
 9126            );
 9127        });
 9128    }
 9129
 9130    #[gpui::test]
 9131    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9132        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9133        let language = Arc::new(Language::new(
 9134            LanguageConfig {
 9135                brackets: vec![BracketPair {
 9136                    start: "{".to_string(),
 9137                    end: "}".to_string(),
 9138                    close: true,
 9139                    newline: true,
 9140                }],
 9141                autoclose_before: "}".to_string(),
 9142                ..Default::default()
 9143            },
 9144            Some(tree_sitter_rust::language()),
 9145        ));
 9146
 9147        let text = r#"
 9148            a
 9149            b
 9150            c
 9151        "#
 9152        .unindent();
 9153
 9154        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9155        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9156        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9157        editor
 9158            .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9159            .await;
 9160
 9161        editor.update(cx, |editor, cx| {
 9162            editor.change_selections(None, cx, |s| {
 9163                s.select_ranges([
 9164                    Point::new(0, 1)..Point::new(0, 1),
 9165                    Point::new(1, 1)..Point::new(1, 1),
 9166                    Point::new(2, 1)..Point::new(2, 1),
 9167                ])
 9168            });
 9169
 9170            editor.handle_input(&Input("{".to_string()), cx);
 9171            editor.handle_input(&Input("{".to_string()), cx);
 9172            editor.handle_input(&Input("_".to_string()), cx);
 9173            assert_eq!(
 9174                editor.text(cx),
 9175                "
 9176                a{{_}}
 9177                b{{_}}
 9178                c{{_}}
 9179                "
 9180                .unindent()
 9181            );
 9182            assert_eq!(
 9183                editor.selections.ranges::<Point>(cx),
 9184                [
 9185                    Point::new(0, 4)..Point::new(0, 4),
 9186                    Point::new(1, 4)..Point::new(1, 4),
 9187                    Point::new(2, 4)..Point::new(2, 4)
 9188                ]
 9189            );
 9190
 9191            editor.backspace(&Default::default(), cx);
 9192            editor.backspace(&Default::default(), cx);
 9193            assert_eq!(
 9194                editor.text(cx),
 9195                "
 9196                a{}
 9197                b{}
 9198                c{}
 9199                "
 9200                .unindent()
 9201            );
 9202            assert_eq!(
 9203                editor.selections.ranges::<Point>(cx),
 9204                [
 9205                    Point::new(0, 2)..Point::new(0, 2),
 9206                    Point::new(1, 2)..Point::new(1, 2),
 9207                    Point::new(2, 2)..Point::new(2, 2)
 9208                ]
 9209            );
 9210
 9211            editor.delete_to_previous_word_start(&Default::default(), cx);
 9212            assert_eq!(
 9213                editor.text(cx),
 9214                "
 9215                a
 9216                b
 9217                c
 9218                "
 9219                .unindent()
 9220            );
 9221            assert_eq!(
 9222                editor.selections.ranges::<Point>(cx),
 9223                [
 9224                    Point::new(0, 1)..Point::new(0, 1),
 9225                    Point::new(1, 1)..Point::new(1, 1),
 9226                    Point::new(2, 1)..Point::new(2, 1)
 9227                ]
 9228            );
 9229        });
 9230    }
 9231
 9232    #[gpui::test]
 9233    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9234        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9235
 9236        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 9237            a.| b
 9238            a.| b
 9239            a.| b"});
 9240        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9241        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9242
 9243        editor.update(cx, |editor, cx| {
 9244            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9245
 9246            editor
 9247                .insert_snippet(&insertion_ranges, snippet, cx)
 9248                .unwrap();
 9249
 9250            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 9251                let range_markers = ('<', '>');
 9252                let (expected_text, mut selection_ranges_lookup) =
 9253                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 9254                let selection_ranges = selection_ranges_lookup
 9255                    .remove(&range_markers.into())
 9256                    .unwrap();
 9257                assert_eq!(editor.text(cx), expected_text);
 9258                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9259            }
 9260            assert(
 9261                editor,
 9262                cx,
 9263                indoc! {"
 9264                    a.f(<one>, two, <three>) b
 9265                    a.f(<one>, two, <three>) b
 9266                    a.f(<one>, two, <three>) b"},
 9267            );
 9268
 9269            // Can't move earlier than the first tab stop
 9270            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9271            assert(
 9272                editor,
 9273                cx,
 9274                indoc! {"
 9275                    a.f(<one>, two, <three>) b
 9276                    a.f(<one>, two, <three>) b
 9277                    a.f(<one>, two, <three>) b"},
 9278            );
 9279
 9280            assert!(editor.move_to_next_snippet_tabstop(cx));
 9281            assert(
 9282                editor,
 9283                cx,
 9284                indoc! {"
 9285                    a.f(one, <two>, three) b
 9286                    a.f(one, <two>, three) b
 9287                    a.f(one, <two>, three) b"},
 9288            );
 9289
 9290            editor.move_to_prev_snippet_tabstop(cx);
 9291            assert(
 9292                editor,
 9293                cx,
 9294                indoc! {"
 9295                    a.f(<one>, two, <three>) b
 9296                    a.f(<one>, two, <three>) b
 9297                    a.f(<one>, two, <three>) b"},
 9298            );
 9299
 9300            assert!(editor.move_to_next_snippet_tabstop(cx));
 9301            assert(
 9302                editor,
 9303                cx,
 9304                indoc! {"
 9305                    a.f(one, <two>, three) b
 9306                    a.f(one, <two>, three) b
 9307                    a.f(one, <two>, three) b"},
 9308            );
 9309            assert!(editor.move_to_next_snippet_tabstop(cx));
 9310            assert(
 9311                editor,
 9312                cx,
 9313                indoc! {"
 9314                    a.f(one, two, three)<> b
 9315                    a.f(one, two, three)<> b
 9316                    a.f(one, two, three)<> b"},
 9317            );
 9318
 9319            // As soon as the last tab stop is reached, snippet state is gone
 9320            editor.move_to_prev_snippet_tabstop(cx);
 9321            assert(
 9322                editor,
 9323                cx,
 9324                indoc! {"
 9325                    a.f(one, two, three)<> b
 9326                    a.f(one, two, three)<> b
 9327                    a.f(one, two, three)<> b"},
 9328            );
 9329        });
 9330    }
 9331
 9332    #[gpui::test]
 9333    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9334        cx.foreground().forbid_parking();
 9335
 9336        let mut language = Language::new(
 9337            LanguageConfig {
 9338                name: "Rust".into(),
 9339                path_suffixes: vec!["rs".to_string()],
 9340                ..Default::default()
 9341            },
 9342            Some(tree_sitter_rust::language()),
 9343        );
 9344        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9345            capabilities: lsp::ServerCapabilities {
 9346                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9347                ..Default::default()
 9348            },
 9349            ..Default::default()
 9350        });
 9351
 9352        let fs = FakeFs::new(cx.background().clone());
 9353        fs.insert_file("/file.rs", Default::default()).await;
 9354
 9355        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9356        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9357        let buffer = project
 9358            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9359            .await
 9360            .unwrap();
 9361
 9362        cx.foreground().start_waiting();
 9363        let fake_server = fake_servers.next().await.unwrap();
 9364
 9365        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9366        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9367        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9368        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9369
 9370        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9371        fake_server
 9372            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9373                assert_eq!(
 9374                    params.text_document.uri,
 9375                    lsp::Url::from_file_path("/file.rs").unwrap()
 9376                );
 9377                assert_eq!(params.options.tab_size, 4);
 9378                Ok(Some(vec![lsp::TextEdit::new(
 9379                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9380                    ", ".to_string(),
 9381                )]))
 9382            })
 9383            .next()
 9384            .await;
 9385        cx.foreground().start_waiting();
 9386        save.await.unwrap();
 9387        assert_eq!(
 9388            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9389            "one, two\nthree\n"
 9390        );
 9391        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9392
 9393        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9394        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9395
 9396        // Ensure we can still save even if formatting hangs.
 9397        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9398            assert_eq!(
 9399                params.text_document.uri,
 9400                lsp::Url::from_file_path("/file.rs").unwrap()
 9401            );
 9402            futures::future::pending::<()>().await;
 9403            unreachable!()
 9404        });
 9405        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9406        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9407        cx.foreground().start_waiting();
 9408        save.await.unwrap();
 9409        assert_eq!(
 9410            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9411            "one\ntwo\nthree\n"
 9412        );
 9413        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9414
 9415        // Set rust language override and assert overriden tabsize is sent to language server
 9416        cx.update(|cx| {
 9417            cx.update_global::<Settings, _, _>(|settings, _| {
 9418                settings.language_overrides.insert(
 9419                    "Rust".into(),
 9420                    LanguageSettings {
 9421                        tab_size: Some(8.try_into().unwrap()),
 9422                        ..Default::default()
 9423                    },
 9424                );
 9425            })
 9426        });
 9427
 9428        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9429        fake_server
 9430            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9431                assert_eq!(
 9432                    params.text_document.uri,
 9433                    lsp::Url::from_file_path("/file.rs").unwrap()
 9434                );
 9435                assert_eq!(params.options.tab_size, 8);
 9436                Ok(Some(vec![]))
 9437            })
 9438            .next()
 9439            .await;
 9440        cx.foreground().start_waiting();
 9441        save.await.unwrap();
 9442    }
 9443
 9444    #[gpui::test]
 9445    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
 9446        cx.foreground().forbid_parking();
 9447
 9448        let mut language = Language::new(
 9449            LanguageConfig {
 9450                name: "Rust".into(),
 9451                path_suffixes: vec!["rs".to_string()],
 9452                ..Default::default()
 9453            },
 9454            Some(tree_sitter_rust::language()),
 9455        );
 9456        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9457            capabilities: lsp::ServerCapabilities {
 9458                document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
 9459                ..Default::default()
 9460            },
 9461            ..Default::default()
 9462        });
 9463
 9464        let fs = FakeFs::new(cx.background().clone());
 9465        fs.insert_file("/file.rs", Default::default()).await;
 9466
 9467        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9468        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9469        let buffer = project
 9470            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9471            .await
 9472            .unwrap();
 9473
 9474        cx.foreground().start_waiting();
 9475        let fake_server = fake_servers.next().await.unwrap();
 9476
 9477        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9478        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9479        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9480        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9481
 9482        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9483        fake_server
 9484            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9485                assert_eq!(
 9486                    params.text_document.uri,
 9487                    lsp::Url::from_file_path("/file.rs").unwrap()
 9488                );
 9489                assert_eq!(params.options.tab_size, 4);
 9490                Ok(Some(vec![lsp::TextEdit::new(
 9491                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9492                    ", ".to_string(),
 9493                )]))
 9494            })
 9495            .next()
 9496            .await;
 9497        cx.foreground().start_waiting();
 9498        save.await.unwrap();
 9499        assert_eq!(
 9500            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9501            "one, two\nthree\n"
 9502        );
 9503        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9504
 9505        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9506        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9507
 9508        // Ensure we can still save even if formatting hangs.
 9509        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
 9510            move |params, _| async move {
 9511                assert_eq!(
 9512                    params.text_document.uri,
 9513                    lsp::Url::from_file_path("/file.rs").unwrap()
 9514                );
 9515                futures::future::pending::<()>().await;
 9516                unreachable!()
 9517            },
 9518        );
 9519        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9520        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9521        cx.foreground().start_waiting();
 9522        save.await.unwrap();
 9523        assert_eq!(
 9524            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9525            "one\ntwo\nthree\n"
 9526        );
 9527        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9528
 9529        // Set rust language override and assert overriden tabsize is sent to language server
 9530        cx.update(|cx| {
 9531            cx.update_global::<Settings, _, _>(|settings, _| {
 9532                settings.language_overrides.insert(
 9533                    "Rust".into(),
 9534                    LanguageSettings {
 9535                        tab_size: Some(8.try_into().unwrap()),
 9536                        ..Default::default()
 9537                    },
 9538                );
 9539            })
 9540        });
 9541
 9542        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9543        fake_server
 9544            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9545                assert_eq!(
 9546                    params.text_document.uri,
 9547                    lsp::Url::from_file_path("/file.rs").unwrap()
 9548                );
 9549                assert_eq!(params.options.tab_size, 8);
 9550                Ok(Some(vec![]))
 9551            })
 9552            .next()
 9553            .await;
 9554        cx.foreground().start_waiting();
 9555        save.await.unwrap();
 9556    }
 9557
 9558    #[gpui::test]
 9559    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9560        let mut language = Language::new(
 9561            LanguageConfig {
 9562                name: "Rust".into(),
 9563                path_suffixes: vec!["rs".to_string()],
 9564                ..Default::default()
 9565            },
 9566            Some(tree_sitter_rust::language()),
 9567        );
 9568        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9569            capabilities: lsp::ServerCapabilities {
 9570                completion_provider: Some(lsp::CompletionOptions {
 9571                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9572                    ..Default::default()
 9573                }),
 9574                ..Default::default()
 9575            },
 9576            ..Default::default()
 9577        });
 9578
 9579        let text = "
 9580            one
 9581            two
 9582            three
 9583        "
 9584        .unindent();
 9585
 9586        let fs = FakeFs::new(cx.background().clone());
 9587        fs.insert_file("/file.rs", text).await;
 9588
 9589        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9590        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9591        let buffer = project
 9592            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9593            .await
 9594            .unwrap();
 9595        let mut fake_server = fake_servers.next().await.unwrap();
 9596
 9597        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9598        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9599
 9600        editor.update(cx, |editor, cx| {
 9601            editor.project = Some(project);
 9602            editor.change_selections(None, cx, |s| {
 9603                s.select_ranges([Point::new(0, 3)..Point::new(0, 3)])
 9604            });
 9605            editor.handle_input(&Input(".".to_string()), cx);
 9606        });
 9607
 9608        handle_completion_request(
 9609            &mut fake_server,
 9610            "/file.rs",
 9611            Point::new(0, 4),
 9612            vec![
 9613                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9614                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9615            ],
 9616        )
 9617        .await;
 9618        editor
 9619            .condition(&cx, |editor, _| editor.context_menu_visible())
 9620            .await;
 9621
 9622        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9623            editor.move_down(&MoveDown, cx);
 9624            let apply_additional_edits = editor
 9625                .confirm_completion(&ConfirmCompletion::default(), cx)
 9626                .unwrap();
 9627            assert_eq!(
 9628                editor.text(cx),
 9629                "
 9630                    one.second_completion
 9631                    two
 9632                    three
 9633                "
 9634                .unindent()
 9635            );
 9636            apply_additional_edits
 9637        });
 9638
 9639        handle_resolve_completion_request(
 9640            &mut fake_server,
 9641            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9642        )
 9643        .await;
 9644        apply_additional_edits.await.unwrap();
 9645        assert_eq!(
 9646            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9647            "
 9648                one.second_completion
 9649                two
 9650                three
 9651                additional edit
 9652            "
 9653            .unindent()
 9654        );
 9655
 9656        editor.update(cx, |editor, cx| {
 9657            editor.change_selections(None, cx, |s| {
 9658                s.select_ranges([
 9659                    Point::new(1, 3)..Point::new(1, 3),
 9660                    Point::new(2, 5)..Point::new(2, 5),
 9661                ])
 9662            });
 9663
 9664            editor.handle_input(&Input(" ".to_string()), cx);
 9665            assert!(editor.context_menu.is_none());
 9666            editor.handle_input(&Input("s".to_string()), cx);
 9667            assert!(editor.context_menu.is_none());
 9668        });
 9669
 9670        handle_completion_request(
 9671            &mut fake_server,
 9672            "/file.rs",
 9673            Point::new(2, 7),
 9674            vec![
 9675                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9676                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9677                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9678            ],
 9679        )
 9680        .await;
 9681        editor
 9682            .condition(&cx, |editor, _| editor.context_menu_visible())
 9683            .await;
 9684
 9685        editor.update(cx, |editor, cx| {
 9686            editor.handle_input(&Input("i".to_string()), cx);
 9687        });
 9688
 9689        handle_completion_request(
 9690            &mut fake_server,
 9691            "/file.rs",
 9692            Point::new(2, 8),
 9693            vec![
 9694                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9695                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9696                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9697            ],
 9698        )
 9699        .await;
 9700        editor
 9701            .condition(&cx, |editor, _| editor.context_menu_visible())
 9702            .await;
 9703
 9704        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9705            let apply_additional_edits = editor
 9706                .confirm_completion(&ConfirmCompletion::default(), cx)
 9707                .unwrap();
 9708            assert_eq!(
 9709                editor.text(cx),
 9710                "
 9711                    one.second_completion
 9712                    two sixth_completion
 9713                    three sixth_completion
 9714                    additional edit
 9715                "
 9716                .unindent()
 9717            );
 9718            apply_additional_edits
 9719        });
 9720        handle_resolve_completion_request(&mut fake_server, None).await;
 9721        apply_additional_edits.await.unwrap();
 9722
 9723        async fn handle_completion_request(
 9724            fake: &mut FakeLanguageServer,
 9725            path: &'static str,
 9726            position: Point,
 9727            completions: Vec<(Range<Point>, &'static str)>,
 9728        ) {
 9729            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9730                let completions = completions.clone();
 9731                async move {
 9732                    assert_eq!(
 9733                        params.text_document_position.text_document.uri,
 9734                        lsp::Url::from_file_path(path).unwrap()
 9735                    );
 9736                    assert_eq!(
 9737                        params.text_document_position.position,
 9738                        lsp::Position::new(position.row, position.column)
 9739                    );
 9740                    Ok(Some(lsp::CompletionResponse::Array(
 9741                        completions
 9742                            .iter()
 9743                            .map(|(range, new_text)| lsp::CompletionItem {
 9744                                label: new_text.to_string(),
 9745                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9746                                    range: lsp::Range::new(
 9747                                        lsp::Position::new(range.start.row, range.start.column),
 9748                                        lsp::Position::new(range.start.row, range.start.column),
 9749                                    ),
 9750                                    new_text: new_text.to_string(),
 9751                                })),
 9752                                ..Default::default()
 9753                            })
 9754                            .collect(),
 9755                    )))
 9756                }
 9757            })
 9758            .next()
 9759            .await;
 9760        }
 9761
 9762        async fn handle_resolve_completion_request(
 9763            fake: &mut FakeLanguageServer,
 9764            edit: Option<(Range<Point>, &'static str)>,
 9765        ) {
 9766            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9767                let edit = edit.clone();
 9768                async move {
 9769                    Ok(lsp::CompletionItem {
 9770                        additional_text_edits: edit.map(|(range, new_text)| {
 9771                            vec![lsp::TextEdit::new(
 9772                                lsp::Range::new(
 9773                                    lsp::Position::new(range.start.row, range.start.column),
 9774                                    lsp::Position::new(range.end.row, range.end.column),
 9775                                ),
 9776                                new_text.to_string(),
 9777                            )]
 9778                        }),
 9779                        ..Default::default()
 9780                    })
 9781                }
 9782            })
 9783            .next()
 9784            .await;
 9785        }
 9786    }
 9787
 9788    #[gpui::test]
 9789    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9790        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9791        let language = Arc::new(Language::new(
 9792            LanguageConfig {
 9793                line_comment: Some("// ".to_string()),
 9794                ..Default::default()
 9795            },
 9796            Some(tree_sitter_rust::language()),
 9797        ));
 9798
 9799        let text = "
 9800            fn a() {
 9801                //b();
 9802                // c();
 9803                //  d();
 9804            }
 9805        "
 9806        .unindent();
 9807
 9808        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9809        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9810        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9811
 9812        view.update(cx, |editor, cx| {
 9813            // If multiple selections intersect a line, the line is only
 9814            // toggled once.
 9815            editor.change_selections(None, cx, |s| {
 9816                s.select_display_ranges([
 9817                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9818                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9819                ])
 9820            });
 9821            editor.toggle_comments(&ToggleComments, cx);
 9822            assert_eq!(
 9823                editor.text(cx),
 9824                "
 9825                    fn a() {
 9826                        b();
 9827                        c();
 9828                         d();
 9829                    }
 9830                "
 9831                .unindent()
 9832            );
 9833
 9834            // The comment prefix is inserted at the same column for every line
 9835            // in a selection.
 9836            editor.change_selections(None, cx, |s| {
 9837                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
 9838            });
 9839            editor.toggle_comments(&ToggleComments, cx);
 9840            assert_eq!(
 9841                editor.text(cx),
 9842                "
 9843                    fn a() {
 9844                        // b();
 9845                        // c();
 9846                        //  d();
 9847                    }
 9848                "
 9849                .unindent()
 9850            );
 9851
 9852            // If a selection ends at the beginning of a line, that line is not toggled.
 9853            editor.change_selections(None, cx, |s| {
 9854                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
 9855            });
 9856            editor.toggle_comments(&ToggleComments, cx);
 9857            assert_eq!(
 9858                editor.text(cx),
 9859                "
 9860                        fn a() {
 9861                            // b();
 9862                            c();
 9863                            //  d();
 9864                        }
 9865                    "
 9866                .unindent()
 9867            );
 9868        });
 9869    }
 9870
 9871    #[gpui::test]
 9872    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9873        cx.set_global(Settings::test(cx));
 9874        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9875        let multibuffer = cx.add_model(|cx| {
 9876            let mut multibuffer = MultiBuffer::new(0);
 9877            multibuffer.push_excerpts(
 9878                buffer.clone(),
 9879                [
 9880                    ExcerptRange {
 9881                        context: Point::new(0, 0)..Point::new(0, 4),
 9882                        primary: None,
 9883                    },
 9884                    ExcerptRange {
 9885                        context: Point::new(1, 0)..Point::new(1, 4),
 9886                        primary: None,
 9887                    },
 9888                ],
 9889                cx,
 9890            );
 9891            multibuffer
 9892        });
 9893
 9894        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9895
 9896        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9897        view.update(cx, |view, cx| {
 9898            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9899            view.change_selections(None, cx, |s| {
 9900                s.select_ranges([
 9901                    Point::new(0, 0)..Point::new(0, 0),
 9902                    Point::new(1, 0)..Point::new(1, 0),
 9903                ])
 9904            });
 9905
 9906            view.handle_input(&Input("X".to_string()), cx);
 9907            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9908            assert_eq!(
 9909                view.selections.ranges(cx),
 9910                [
 9911                    Point::new(0, 1)..Point::new(0, 1),
 9912                    Point::new(1, 1)..Point::new(1, 1),
 9913                ]
 9914            )
 9915        });
 9916    }
 9917
 9918    #[gpui::test]
 9919    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9920        cx.set_global(Settings::test(cx));
 9921        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
 9922                [aaaa
 9923                (bbbb]
 9924                cccc)"});
 9925        let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
 9926            context,
 9927            primary: None,
 9928        });
 9929        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
 9930        let multibuffer = cx.add_model(|cx| {
 9931            let mut multibuffer = MultiBuffer::new(0);
 9932            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
 9933            multibuffer
 9934        });
 9935
 9936        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9937        view.update(cx, |view, cx| {
 9938            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
 9939                aaaa
 9940                b|bbb
 9941                b|bb|b
 9942                cccc"});
 9943            assert_eq!(view.text(cx), expected_text);
 9944            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
 9945
 9946            view.handle_input(&Input("X".to_string()), cx);
 9947
 9948            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9949                aaaa
 9950                bX|bbXb
 9951                bX|bbX|b
 9952                cccc"});
 9953            assert_eq!(view.text(cx), expected_text);
 9954            assert_eq!(view.selections.ranges(cx), expected_selections);
 9955
 9956            view.newline(&Newline, cx);
 9957            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9958                aaaa
 9959                bX
 9960                |bbX
 9961                b
 9962                bX
 9963                |bbX
 9964                |b
 9965                cccc"});
 9966            assert_eq!(view.text(cx), expected_text);
 9967            assert_eq!(view.selections.ranges(cx), expected_selections);
 9968        });
 9969    }
 9970
 9971    #[gpui::test]
 9972    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9973        cx.set_global(Settings::test(cx));
 9974        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9975        let mut excerpt1_id = None;
 9976        let multibuffer = cx.add_model(|cx| {
 9977            let mut multibuffer = MultiBuffer::new(0);
 9978            excerpt1_id = multibuffer
 9979                .push_excerpts(
 9980                    buffer.clone(),
 9981                    [
 9982                        ExcerptRange {
 9983                            context: Point::new(0, 0)..Point::new(1, 4),
 9984                            primary: None,
 9985                        },
 9986                        ExcerptRange {
 9987                            context: Point::new(1, 0)..Point::new(2, 4),
 9988                            primary: None,
 9989                        },
 9990                    ],
 9991                    cx,
 9992                )
 9993                .into_iter()
 9994                .next();
 9995            multibuffer
 9996        });
 9997        assert_eq!(
 9998            multibuffer.read(cx).read(cx).text(),
 9999            "aaaa\nbbbb\nbbbb\ncccc"
10000        );
10001        let (_, editor) = cx.add_window(Default::default(), |cx| {
10002            let mut editor = build_editor(multibuffer.clone(), cx);
10003            let snapshot = editor.snapshot(cx);
10004            editor.change_selections(None, cx, |s| {
10005                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
10006            });
10007            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
10008            assert_eq!(
10009                editor.selections.ranges(cx),
10010                [
10011                    Point::new(1, 3)..Point::new(1, 3),
10012                    Point::new(2, 1)..Point::new(2, 1),
10013                ]
10014            );
10015            editor
10016        });
10017
10018        // Refreshing selections is a no-op when excerpts haven't changed.
10019        editor.update(cx, |editor, cx| {
10020            editor.change_selections(None, cx, |s| {
10021                s.refresh();
10022            });
10023            assert_eq!(
10024                editor.selections.ranges(cx),
10025                [
10026                    Point::new(1, 3)..Point::new(1, 3),
10027                    Point::new(2, 1)..Point::new(2, 1),
10028                ]
10029            );
10030        });
10031
10032        multibuffer.update(cx, |multibuffer, cx| {
10033            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10034        });
10035        editor.update(cx, |editor, cx| {
10036            // Removing an excerpt causes the first selection to become degenerate.
10037            assert_eq!(
10038                editor.selections.ranges(cx),
10039                [
10040                    Point::new(0, 0)..Point::new(0, 0),
10041                    Point::new(0, 1)..Point::new(0, 1)
10042                ]
10043            );
10044
10045            // Refreshing selections will relocate the first selection to the original buffer
10046            // location.
10047            editor.change_selections(None, cx, |s| {
10048                s.refresh();
10049            });
10050            assert_eq!(
10051                editor.selections.ranges(cx),
10052                [
10053                    Point::new(0, 1)..Point::new(0, 1),
10054                    Point::new(0, 3)..Point::new(0, 3)
10055                ]
10056            );
10057            assert!(editor.selections.pending_anchor().is_some());
10058        });
10059    }
10060
10061    #[gpui::test]
10062    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10063        cx.set_global(Settings::test(cx));
10064        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10065        let mut excerpt1_id = None;
10066        let multibuffer = cx.add_model(|cx| {
10067            let mut multibuffer = MultiBuffer::new(0);
10068            excerpt1_id = multibuffer
10069                .push_excerpts(
10070                    buffer.clone(),
10071                    [
10072                        ExcerptRange {
10073                            context: Point::new(0, 0)..Point::new(1, 4),
10074                            primary: None,
10075                        },
10076                        ExcerptRange {
10077                            context: Point::new(1, 0)..Point::new(2, 4),
10078                            primary: None,
10079                        },
10080                    ],
10081                    cx,
10082                )
10083                .into_iter()
10084                .next();
10085            multibuffer
10086        });
10087        assert_eq!(
10088            multibuffer.read(cx).read(cx).text(),
10089            "aaaa\nbbbb\nbbbb\ncccc"
10090        );
10091        let (_, editor) = cx.add_window(Default::default(), |cx| {
10092            let mut editor = build_editor(multibuffer.clone(), cx);
10093            let snapshot = editor.snapshot(cx);
10094            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10095            assert_eq!(
10096                editor.selections.ranges(cx),
10097                [Point::new(1, 3)..Point::new(1, 3)]
10098            );
10099            editor
10100        });
10101
10102        multibuffer.update(cx, |multibuffer, cx| {
10103            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10104        });
10105        editor.update(cx, |editor, cx| {
10106            assert_eq!(
10107                editor.selections.ranges(cx),
10108                [Point::new(0, 0)..Point::new(0, 0)]
10109            );
10110
10111            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10112            editor.change_selections(None, cx, |s| {
10113                s.refresh();
10114            });
10115            assert_eq!(
10116                editor.selections.ranges(cx),
10117                [Point::new(0, 3)..Point::new(0, 3)]
10118            );
10119            assert!(editor.selections.pending_anchor().is_some());
10120        });
10121    }
10122
10123    #[gpui::test]
10124    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10125        cx.update(|cx| cx.set_global(Settings::test(cx)));
10126        let language = Arc::new(
10127            Language::new(
10128                LanguageConfig {
10129                    brackets: vec![
10130                        BracketPair {
10131                            start: "{".to_string(),
10132                            end: "}".to_string(),
10133                            close: true,
10134                            newline: true,
10135                        },
10136                        BracketPair {
10137                            start: "/* ".to_string(),
10138                            end: " */".to_string(),
10139                            close: true,
10140                            newline: true,
10141                        },
10142                    ],
10143                    ..Default::default()
10144                },
10145                Some(tree_sitter_rust::language()),
10146            )
10147            .with_indents_query("")
10148            .unwrap(),
10149        );
10150
10151        let text = concat!(
10152            "{   }\n",     // Suppress rustfmt
10153            "  x\n",       //
10154            "  /*   */\n", //
10155            "x\n",         //
10156            "{{} }\n",     //
10157        );
10158
10159        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10160        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10161        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10162        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10163            .await;
10164
10165        view.update(cx, |view, cx| {
10166            view.change_selections(None, cx, |s| {
10167                s.select_display_ranges([
10168                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10169                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10170                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10171                ])
10172            });
10173            view.newline(&Newline, cx);
10174
10175            assert_eq!(
10176                view.buffer().read(cx).read(cx).text(),
10177                concat!(
10178                    "{ \n",    // Suppress rustfmt
10179                    "\n",      //
10180                    "}\n",     //
10181                    "  x\n",   //
10182                    "  /* \n", //
10183                    "  \n",    //
10184                    "  */\n",  //
10185                    "x\n",     //
10186                    "{{} \n",  //
10187                    "}\n",     //
10188                )
10189            );
10190        });
10191    }
10192
10193    #[gpui::test]
10194    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10195        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10196
10197        cx.set_global(Settings::test(cx));
10198        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10199
10200        editor.update(cx, |editor, cx| {
10201            struct Type1;
10202            struct Type2;
10203
10204            let buffer = buffer.read(cx).snapshot(cx);
10205
10206            let anchor_range = |range: Range<Point>| {
10207                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10208            };
10209
10210            editor.highlight_background::<Type1>(
10211                vec![
10212                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10213                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10214                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10215                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10216                ],
10217                |_| Color::red(),
10218                cx,
10219            );
10220            editor.highlight_background::<Type2>(
10221                vec![
10222                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10223                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10224                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10225                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10226                ],
10227                |_| Color::green(),
10228                cx,
10229            );
10230
10231            let snapshot = editor.snapshot(cx);
10232            let mut highlighted_ranges = editor.background_highlights_in_range(
10233                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10234                &snapshot,
10235                cx.global::<Settings>().theme.as_ref(),
10236            );
10237            // Enforce a consistent ordering based on color without relying on the ordering of the
10238            // highlight's `TypeId` which is non-deterministic.
10239            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10240            assert_eq!(
10241                highlighted_ranges,
10242                &[
10243                    (
10244                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10245                        Color::green(),
10246                    ),
10247                    (
10248                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10249                        Color::green(),
10250                    ),
10251                    (
10252                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10253                        Color::red(),
10254                    ),
10255                    (
10256                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10257                        Color::red(),
10258                    ),
10259                ]
10260            );
10261            assert_eq!(
10262                editor.background_highlights_in_range(
10263                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10264                    &snapshot,
10265                    cx.global::<Settings>().theme.as_ref(),
10266                ),
10267                &[(
10268                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10269                    Color::red(),
10270                )]
10271            );
10272        });
10273    }
10274
10275    #[gpui::test]
10276    fn test_following(cx: &mut gpui::MutableAppContext) {
10277        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10278
10279        cx.set_global(Settings::test(cx));
10280
10281        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10282        let (_, follower) = cx.add_window(
10283            WindowOptions {
10284                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10285                ..Default::default()
10286            },
10287            |cx| build_editor(buffer.clone(), cx),
10288        );
10289
10290        let pending_update = Rc::new(RefCell::new(None));
10291        follower.update(cx, {
10292            let update = pending_update.clone();
10293            |_, cx| {
10294                cx.subscribe(&leader, move |_, leader, event, cx| {
10295                    leader
10296                        .read(cx)
10297                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10298                })
10299                .detach();
10300            }
10301        });
10302
10303        // Update the selections only
10304        leader.update(cx, |leader, cx| {
10305            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10306        });
10307        follower.update(cx, |follower, cx| {
10308            follower
10309                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10310                .unwrap();
10311        });
10312        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
10313
10314        // Update the scroll position only
10315        leader.update(cx, |leader, cx| {
10316            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10317        });
10318        follower.update(cx, |follower, cx| {
10319            follower
10320                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10321                .unwrap();
10322        });
10323        assert_eq!(
10324            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10325            vec2f(1.5, 3.5)
10326        );
10327
10328        // Update the selections and scroll position
10329        leader.update(cx, |leader, cx| {
10330            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
10331            leader.request_autoscroll(Autoscroll::Newest, cx);
10332            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10333        });
10334        follower.update(cx, |follower, cx| {
10335            let initial_scroll_position = follower.scroll_position(cx);
10336            follower
10337                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10338                .unwrap();
10339            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10340            assert!(follower.autoscroll_request.is_some());
10341        });
10342        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
10343
10344        // Creating a pending selection that precedes another selection
10345        leader.update(cx, |leader, cx| {
10346            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10347            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10348        });
10349        follower.update(cx, |follower, cx| {
10350            follower
10351                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10352                .unwrap();
10353        });
10354        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
10355
10356        // Extend the pending selection so that it surrounds another selection
10357        leader.update(cx, |leader, cx| {
10358            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10359        });
10360        follower.update(cx, |follower, cx| {
10361            follower
10362                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10363                .unwrap();
10364        });
10365        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
10366    }
10367
10368    #[test]
10369    fn test_combine_syntax_and_fuzzy_match_highlights() {
10370        let string = "abcdefghijklmnop";
10371        let syntax_ranges = [
10372            (
10373                0..3,
10374                HighlightStyle {
10375                    color: Some(Color::red()),
10376                    ..Default::default()
10377                },
10378            ),
10379            (
10380                4..8,
10381                HighlightStyle {
10382                    color: Some(Color::green()),
10383                    ..Default::default()
10384                },
10385            ),
10386        ];
10387        let match_indices = [4, 6, 7, 8];
10388        assert_eq!(
10389            combine_syntax_and_fuzzy_match_highlights(
10390                &string,
10391                Default::default(),
10392                syntax_ranges.into_iter(),
10393                &match_indices,
10394            ),
10395            &[
10396                (
10397                    0..3,
10398                    HighlightStyle {
10399                        color: Some(Color::red()),
10400                        ..Default::default()
10401                    },
10402                ),
10403                (
10404                    4..5,
10405                    HighlightStyle {
10406                        color: Some(Color::green()),
10407                        weight: Some(fonts::Weight::BOLD),
10408                        ..Default::default()
10409                    },
10410                ),
10411                (
10412                    5..6,
10413                    HighlightStyle {
10414                        color: Some(Color::green()),
10415                        ..Default::default()
10416                    },
10417                ),
10418                (
10419                    6..8,
10420                    HighlightStyle {
10421                        color: Some(Color::green()),
10422                        weight: Some(fonts::Weight::BOLD),
10423                        ..Default::default()
10424                    },
10425                ),
10426                (
10427                    8..9,
10428                    HighlightStyle {
10429                        weight: Some(fonts::Weight::BOLD),
10430                        ..Default::default()
10431                    },
10432                ),
10433            ]
10434        );
10435    }
10436
10437    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10438        let point = DisplayPoint::new(row as u32, column as u32);
10439        point..point
10440    }
10441
10442    fn assert_selection_ranges(
10443        marked_text: &str,
10444        selection_marker_pairs: Vec<(char, char)>,
10445        view: &mut Editor,
10446        cx: &mut ViewContext<Editor>,
10447    ) {
10448        let snapshot = view.snapshot(cx).display_snapshot;
10449        let mut marker_chars = Vec::new();
10450        for (start, end) in selection_marker_pairs.iter() {
10451            marker_chars.push(*start);
10452            marker_chars.push(*end);
10453        }
10454        let (_, markers) = marked_text_by(marked_text, marker_chars);
10455        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10456            .iter()
10457            .map(|(start, end)| {
10458                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10459                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10460                start..end
10461            })
10462            .collect();
10463        assert_eq!(
10464            view.selections.display_ranges(cx),
10465            &asserted_ranges[..],
10466            "Assert selections are {}",
10467            marked_text
10468        );
10469    }
10470}
10471
10472trait RangeExt<T> {
10473    fn sorted(&self) -> Range<T>;
10474    fn to_inclusive(&self) -> RangeInclusive<T>;
10475}
10476
10477impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10478    fn sorted(&self) -> Self {
10479        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10480    }
10481
10482    fn to_inclusive(&self) -> RangeInclusive<T> {
10483        self.start.clone()..=self.end.clone()
10484    }
10485}