editor.rs

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