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