editor.rs

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