editor.rs

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