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