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