editor.rs

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