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