editor.rs

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