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::{hide_link_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::<CompletionTag>::new(
  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::<ActionTag>::new(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 has_pending_nonempty_selection(&self) -> bool {
 1793        let pending_nonempty_selection = match self.selections.pending_anchor() {
 1794            Some(Selection { start, end, .. }) => start != end,
 1795            None => false,
 1796        };
 1797        pending_nonempty_selection || self.columnar_selection_tail.is_some()
 1798    }
 1799
 1800    pub fn has_pending_selection(&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::<Tag>::new(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                        hide_link_definition(editor, cx);
 6014                    })
 6015                }
 6016            });
 6017        }
 6018
 6019        Stack::new()
 6020            .with_child(
 6021                EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed(),
 6022            )
 6023            .with_child(ChildView::new(&self.mouse_context_menu).boxed())
 6024            .boxed()
 6025    }
 6026
 6027    fn ui_name() -> &'static str {
 6028        "Editor"
 6029    }
 6030
 6031    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
 6032        let focused_event = EditorFocused(cx.handle());
 6033        cx.emit_global(focused_event);
 6034        if let Some(rename) = self.pending_rename.as_ref() {
 6035            cx.focus(&rename.editor);
 6036        } else {
 6037            self.focused = true;
 6038            self.blink_cursors(self.blink_epoch, cx);
 6039            self.buffer.update(cx, |buffer, cx| {
 6040                buffer.finalize_last_transaction(cx);
 6041                if self.leader_replica_id.is_none() {
 6042                    buffer.set_active_selections(
 6043                        &self.selections.disjoint_anchors(),
 6044                        self.selections.line_mode,
 6045                        cx,
 6046                    );
 6047                }
 6048            });
 6049        }
 6050    }
 6051
 6052    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
 6053        let blurred_event = EditorBlurred(cx.handle());
 6054        cx.emit_global(blurred_event);
 6055        self.focused = false;
 6056        self.buffer
 6057            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6058        self.hide_context_menu(cx);
 6059        hide_hover(self, cx);
 6060        cx.emit(Event::Blurred);
 6061        cx.notify();
 6062    }
 6063
 6064    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6065        let mut context = Self::default_keymap_context();
 6066        let mode = match self.mode {
 6067            EditorMode::SingleLine => "single_line",
 6068            EditorMode::AutoHeight { .. } => "auto_height",
 6069            EditorMode::Full => "full",
 6070        };
 6071        context.map.insert("mode".into(), mode.into());
 6072        if self.pending_rename.is_some() {
 6073            context.set.insert("renaming".into());
 6074        }
 6075        match self.context_menu.as_ref() {
 6076            Some(ContextMenu::Completions(_)) => {
 6077                context.set.insert("showing_completions".into());
 6078            }
 6079            Some(ContextMenu::CodeActions(_)) => {
 6080                context.set.insert("showing_code_actions".into());
 6081            }
 6082            None => {}
 6083        }
 6084
 6085        for layer in self.keymap_context_layers.values() {
 6086            context.extend(layer);
 6087        }
 6088
 6089        context
 6090    }
 6091
 6092    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
 6093        Some(
 6094            self.buffer
 6095                .read(cx)
 6096                .read(cx)
 6097                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 6098                .collect(),
 6099        )
 6100    }
 6101
 6102    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6103        // Prevent the IME menu from appearing when holding down an alphabetic key
 6104        // while input is disabled.
 6105        if !self.input_enabled {
 6106            return None;
 6107        }
 6108
 6109        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 6110        Some(range.start.0..range.end.0)
 6111    }
 6112
 6113    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6114        let snapshot = self.buffer.read(cx).read(cx);
 6115        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 6116        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 6117    }
 6118
 6119    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 6120        self.clear_text_highlights::<InputComposition>(cx);
 6121        self.ime_transaction.take();
 6122    }
 6123
 6124    fn replace_text_in_range(
 6125        &mut self,
 6126        range_utf16: Option<Range<usize>>,
 6127        text: &str,
 6128        cx: &mut ViewContext<Self>,
 6129    ) {
 6130        if !self.input_enabled {
 6131            cx.emit(Event::IgnoredInput);
 6132            return;
 6133        }
 6134
 6135        self.transact(cx, |this, cx| {
 6136            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 6137                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6138                Some(this.selection_replacement_ranges(range_utf16, cx))
 6139            } else {
 6140                this.marked_text_ranges(cx)
 6141            };
 6142
 6143            if let Some(new_selected_ranges) = new_selected_ranges {
 6144                this.change_selections(None, cx, |selections| {
 6145                    selections.select_ranges(new_selected_ranges)
 6146                });
 6147            }
 6148            this.handle_input(text, cx);
 6149        });
 6150
 6151        if let Some(transaction) = self.ime_transaction {
 6152            self.buffer.update(cx, |buffer, cx| {
 6153                buffer.group_until_transaction(transaction, cx);
 6154            });
 6155        }
 6156
 6157        self.unmark_text(cx);
 6158    }
 6159
 6160    fn replace_and_mark_text_in_range(
 6161        &mut self,
 6162        range_utf16: Option<Range<usize>>,
 6163        text: &str,
 6164        new_selected_range_utf16: Option<Range<usize>>,
 6165        cx: &mut ViewContext<Self>,
 6166    ) {
 6167        if !self.input_enabled {
 6168            cx.emit(Event::IgnoredInput);
 6169            return;
 6170        }
 6171
 6172        let transaction = self.transact(cx, |this, cx| {
 6173            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 6174                let snapshot = this.buffer.read(cx).read(cx);
 6175                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 6176                    for marked_range in &mut marked_ranges {
 6177                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 6178                        marked_range.start.0 += relative_range_utf16.start;
 6179                        marked_range.start =
 6180                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 6181                        marked_range.end =
 6182                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 6183                    }
 6184                }
 6185                Some(marked_ranges)
 6186            } else if let Some(range_utf16) = range_utf16 {
 6187                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6188                Some(this.selection_replacement_ranges(range_utf16, cx))
 6189            } else {
 6190                None
 6191            };
 6192
 6193            if let Some(ranges) = ranges_to_replace {
 6194                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 6195            }
 6196
 6197            let marked_ranges = {
 6198                let snapshot = this.buffer.read(cx).read(cx);
 6199                this.selections
 6200                    .disjoint_anchors()
 6201                    .iter()
 6202                    .map(|selection| {
 6203                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 6204                    })
 6205                    .collect::<Vec<_>>()
 6206            };
 6207
 6208            if text.is_empty() {
 6209                this.unmark_text(cx);
 6210            } else {
 6211                this.highlight_text::<InputComposition>(
 6212                    marked_ranges.clone(),
 6213                    this.style(cx).composition_mark,
 6214                    cx,
 6215                );
 6216            }
 6217
 6218            this.handle_input(text, cx);
 6219
 6220            if let Some(new_selected_range) = new_selected_range_utf16 {
 6221                let snapshot = this.buffer.read(cx).read(cx);
 6222                let new_selected_ranges = marked_ranges
 6223                    .into_iter()
 6224                    .map(|marked_range| {
 6225                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 6226                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 6227                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 6228                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 6229                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 6230                    })
 6231                    .collect::<Vec<_>>();
 6232
 6233                drop(snapshot);
 6234                this.change_selections(None, cx, |selections| {
 6235                    selections.select_ranges(new_selected_ranges)
 6236                });
 6237            }
 6238        });
 6239
 6240        self.ime_transaction = self.ime_transaction.or(transaction);
 6241        if let Some(transaction) = self.ime_transaction {
 6242            self.buffer.update(cx, |buffer, cx| {
 6243                buffer.group_until_transaction(transaction, cx);
 6244            });
 6245        }
 6246
 6247        if self.text_highlights::<InputComposition>(cx).is_none() {
 6248            self.ime_transaction.take();
 6249        }
 6250    }
 6251}
 6252
 6253fn build_style(
 6254    settings: &Settings,
 6255    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6256    override_text_style: Option<&OverrideTextStyle>,
 6257    cx: &AppContext,
 6258) -> EditorStyle {
 6259    let font_cache = cx.font_cache();
 6260
 6261    let mut theme = settings.theme.editor.clone();
 6262    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6263        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6264        theme.text_color = field_editor_theme.text.color;
 6265        theme.selection = field_editor_theme.selection;
 6266        theme.background = field_editor_theme
 6267            .container
 6268            .background_color
 6269            .unwrap_or_default();
 6270        EditorStyle {
 6271            text: field_editor_theme.text,
 6272            placeholder_text: field_editor_theme.placeholder_text,
 6273            theme,
 6274        }
 6275    } else {
 6276        let font_family_id = settings.buffer_font_family;
 6277        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6278        let font_properties = Default::default();
 6279        let font_id = font_cache
 6280            .select_font(font_family_id, &font_properties)
 6281            .unwrap();
 6282        let font_size = settings.buffer_font_size;
 6283        EditorStyle {
 6284            text: TextStyle {
 6285                color: settings.theme.editor.text_color,
 6286                font_family_name,
 6287                font_family_id,
 6288                font_id,
 6289                font_size,
 6290                font_properties,
 6291                underline: Default::default(),
 6292            },
 6293            placeholder_text: None,
 6294            theme,
 6295        }
 6296    };
 6297
 6298    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6299        if let Some(highlighted) = style
 6300            .text
 6301            .clone()
 6302            .highlight(highlight_style, font_cache)
 6303            .log_err()
 6304        {
 6305            style.text = highlighted;
 6306        }
 6307    }
 6308
 6309    style
 6310}
 6311
 6312trait SelectionExt {
 6313    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6314    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6315    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6316    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6317        -> Range<u32>;
 6318}
 6319
 6320impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6321    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6322        let start = self.start.to_point(buffer);
 6323        let end = self.end.to_point(buffer);
 6324        if self.reversed {
 6325            end..start
 6326        } else {
 6327            start..end
 6328        }
 6329    }
 6330
 6331    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6332        let start = self.start.to_offset(buffer);
 6333        let end = self.end.to_offset(buffer);
 6334        if self.reversed {
 6335            end..start
 6336        } else {
 6337            start..end
 6338        }
 6339    }
 6340
 6341    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6342        let start = self
 6343            .start
 6344            .to_point(&map.buffer_snapshot)
 6345            .to_display_point(map);
 6346        let end = self
 6347            .end
 6348            .to_point(&map.buffer_snapshot)
 6349            .to_display_point(map);
 6350        if self.reversed {
 6351            end..start
 6352        } else {
 6353            start..end
 6354        }
 6355    }
 6356
 6357    fn spanned_rows(
 6358        &self,
 6359        include_end_if_at_line_start: bool,
 6360        map: &DisplaySnapshot,
 6361    ) -> Range<u32> {
 6362        let start = self.start.to_point(&map.buffer_snapshot);
 6363        let mut end = self.end.to_point(&map.buffer_snapshot);
 6364        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6365            end.row -= 1;
 6366        }
 6367
 6368        let buffer_start = map.prev_line_boundary(start).0;
 6369        let buffer_end = map.next_line_boundary(end).0;
 6370        buffer_start.row..buffer_end.row + 1
 6371    }
 6372}
 6373
 6374impl<T: InvalidationRegion> InvalidationStack<T> {
 6375    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6376    where
 6377        S: Clone + ToOffset,
 6378    {
 6379        while let Some(region) = self.last() {
 6380            let all_selections_inside_invalidation_ranges =
 6381                if selections.len() == region.ranges().len() {
 6382                    selections
 6383                        .iter()
 6384                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 6385                        .all(|(selection, invalidation_range)| {
 6386                            let head = selection.head().to_offset(buffer);
 6387                            invalidation_range.start <= head && invalidation_range.end >= head
 6388                        })
 6389                } else {
 6390                    false
 6391                };
 6392
 6393            if all_selections_inside_invalidation_ranges {
 6394                break;
 6395            } else {
 6396                self.pop();
 6397            }
 6398        }
 6399    }
 6400}
 6401
 6402impl<T> Default for InvalidationStack<T> {
 6403    fn default() -> Self {
 6404        Self(Default::default())
 6405    }
 6406}
 6407
 6408impl<T> Deref for InvalidationStack<T> {
 6409    type Target = Vec<T>;
 6410
 6411    fn deref(&self) -> &Self::Target {
 6412        &self.0
 6413    }
 6414}
 6415
 6416impl<T> DerefMut for InvalidationStack<T> {
 6417    fn deref_mut(&mut self) -> &mut Self::Target {
 6418        &mut self.0
 6419    }
 6420}
 6421
 6422impl InvalidationRegion for BracketPairState {
 6423    fn ranges(&self) -> &[Range<Anchor>] {
 6424        &self.ranges
 6425    }
 6426}
 6427
 6428impl InvalidationRegion for SnippetState {
 6429    fn ranges(&self) -> &[Range<Anchor>] {
 6430        &self.ranges[self.active_index]
 6431    }
 6432}
 6433
 6434impl Deref for EditorStyle {
 6435    type Target = theme::Editor;
 6436
 6437    fn deref(&self) -> &Self::Target {
 6438        &self.theme
 6439    }
 6440}
 6441
 6442pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6443    let mut highlighted_lines = Vec::new();
 6444    for line in diagnostic.message.lines() {
 6445        highlighted_lines.push(highlight_diagnostic_message(line));
 6446    }
 6447
 6448    Arc::new(move |cx: &mut BlockContext| {
 6449        let settings = cx.global::<Settings>();
 6450        let theme = &settings.theme.editor;
 6451        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6452        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6453        Flex::column()
 6454            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6455                Label::new(
 6456                    line.clone(),
 6457                    style.message.clone().with_font_size(font_size),
 6458                )
 6459                .with_highlights(highlights.clone())
 6460                .contained()
 6461                .with_margin_left(cx.anchor_x)
 6462                .boxed()
 6463            }))
 6464            .aligned()
 6465            .left()
 6466            .boxed()
 6467    })
 6468}
 6469
 6470pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6471    let mut message_without_backticks = String::new();
 6472    let mut prev_offset = 0;
 6473    let mut inside_block = false;
 6474    let mut highlights = Vec::new();
 6475    for (match_ix, (offset, _)) in message
 6476        .match_indices('`')
 6477        .chain([(message.len(), "")])
 6478        .enumerate()
 6479    {
 6480        message_without_backticks.push_str(&message[prev_offset..offset]);
 6481        if inside_block {
 6482            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6483        }
 6484
 6485        inside_block = !inside_block;
 6486        prev_offset = offset + 1;
 6487    }
 6488
 6489    (message_without_backticks, highlights)
 6490}
 6491
 6492pub fn diagnostic_style(
 6493    severity: DiagnosticSeverity,
 6494    valid: bool,
 6495    theme: &theme::Editor,
 6496) -> DiagnosticStyle {
 6497    match (severity, valid) {
 6498        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6499        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6500        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6501        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6502        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6503        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6504        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6505        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6506        _ => theme.invalid_hint_diagnostic.clone(),
 6507    }
 6508}
 6509
 6510pub fn combine_syntax_and_fuzzy_match_highlights(
 6511    text: &str,
 6512    default_style: HighlightStyle,
 6513    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6514    match_indices: &[usize],
 6515) -> Vec<(Range<usize>, HighlightStyle)> {
 6516    let mut result = Vec::new();
 6517    let mut match_indices = match_indices.iter().copied().peekable();
 6518
 6519    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6520    {
 6521        syntax_highlight.weight = None;
 6522
 6523        // Add highlights for any fuzzy match characters before the next
 6524        // syntax highlight range.
 6525        while let Some(&match_index) = match_indices.peek() {
 6526            if match_index >= range.start {
 6527                break;
 6528            }
 6529            match_indices.next();
 6530            let end_index = char_ix_after(match_index, text);
 6531            let mut match_style = default_style;
 6532            match_style.weight = Some(fonts::Weight::BOLD);
 6533            result.push((match_index..end_index, match_style));
 6534        }
 6535
 6536        if range.start == usize::MAX {
 6537            break;
 6538        }
 6539
 6540        // Add highlights for any fuzzy match characters within the
 6541        // syntax highlight range.
 6542        let mut offset = range.start;
 6543        while let Some(&match_index) = match_indices.peek() {
 6544            if match_index >= range.end {
 6545                break;
 6546            }
 6547
 6548            match_indices.next();
 6549            if match_index > offset {
 6550                result.push((offset..match_index, syntax_highlight));
 6551            }
 6552
 6553            let mut end_index = char_ix_after(match_index, text);
 6554            while let Some(&next_match_index) = match_indices.peek() {
 6555                if next_match_index == end_index && next_match_index < range.end {
 6556                    end_index = char_ix_after(next_match_index, text);
 6557                    match_indices.next();
 6558                } else {
 6559                    break;
 6560                }
 6561            }
 6562
 6563            let mut match_style = syntax_highlight;
 6564            match_style.weight = Some(fonts::Weight::BOLD);
 6565            result.push((match_index..end_index, match_style));
 6566            offset = end_index;
 6567        }
 6568
 6569        if offset < range.end {
 6570            result.push((offset..range.end, syntax_highlight));
 6571        }
 6572    }
 6573
 6574    fn char_ix_after(ix: usize, text: &str) -> usize {
 6575        ix + text[ix..].chars().next().unwrap().len_utf8()
 6576    }
 6577
 6578    result
 6579}
 6580
 6581pub fn styled_runs_for_code_label<'a>(
 6582    label: &'a CodeLabel,
 6583    syntax_theme: &'a theme::SyntaxTheme,
 6584) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6585    let fade_out = HighlightStyle {
 6586        fade_out: Some(0.35),
 6587        ..Default::default()
 6588    };
 6589
 6590    let mut prev_end = label.filter_range.end;
 6591    label
 6592        .runs
 6593        .iter()
 6594        .enumerate()
 6595        .flat_map(move |(ix, (range, highlight_id))| {
 6596            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6597                style
 6598            } else {
 6599                return Default::default();
 6600            };
 6601            let mut muted_style = style;
 6602            muted_style.highlight(fade_out);
 6603
 6604            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6605            if range.start >= label.filter_range.end {
 6606                if range.start > prev_end {
 6607                    runs.push((prev_end..range.start, fade_out));
 6608                }
 6609                runs.push((range.clone(), muted_style));
 6610            } else if range.end <= label.filter_range.end {
 6611                runs.push((range.clone(), style));
 6612            } else {
 6613                runs.push((range.start..label.filter_range.end, style));
 6614                runs.push((label.filter_range.end..range.end, muted_style));
 6615            }
 6616            prev_end = cmp::max(prev_end, range.end);
 6617
 6618            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6619                runs.push((prev_end..label.text.len(), fade_out));
 6620            }
 6621
 6622            runs
 6623        })
 6624}
 6625
 6626#[cfg(test)]
 6627mod tests {
 6628    use crate::test::{
 6629        assert_text_with_selections, build_editor, select_ranges, EditorLspTestContext,
 6630        EditorTestContext,
 6631    };
 6632
 6633    use super::*;
 6634    use futures::StreamExt;
 6635    use gpui::{
 6636        geometry::rect::RectF,
 6637        platform::{WindowBounds, WindowOptions},
 6638    };
 6639    use indoc::indoc;
 6640    use language::{FakeLspAdapter, LanguageConfig};
 6641    use project::FakeFs;
 6642    use settings::EditorSettings;
 6643    use std::{cell::RefCell, rc::Rc, time::Instant};
 6644    use text::Point;
 6645    use unindent::Unindent;
 6646    use util::{
 6647        assert_set_eq,
 6648        test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
 6649    };
 6650    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6651
 6652    #[gpui::test]
 6653    fn test_edit_events(cx: &mut MutableAppContext) {
 6654        cx.set_global(Settings::test(cx));
 6655        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6656
 6657        let events = Rc::new(RefCell::new(Vec::new()));
 6658        let (_, editor1) = cx.add_window(Default::default(), {
 6659            let events = events.clone();
 6660            |cx| {
 6661                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6662                    if matches!(
 6663                        event,
 6664                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6665                    ) {
 6666                        events.borrow_mut().push(("editor1", *event));
 6667                    }
 6668                })
 6669                .detach();
 6670                Editor::for_buffer(buffer.clone(), None, cx)
 6671            }
 6672        });
 6673        let (_, editor2) = cx.add_window(Default::default(), {
 6674            let events = events.clone();
 6675            |cx| {
 6676                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6677                    if matches!(
 6678                        event,
 6679                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6680                    ) {
 6681                        events.borrow_mut().push(("editor2", *event));
 6682                    }
 6683                })
 6684                .detach();
 6685                Editor::for_buffer(buffer.clone(), None, cx)
 6686            }
 6687        });
 6688        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6689
 6690        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6691        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6692        assert_eq!(
 6693            mem::take(&mut *events.borrow_mut()),
 6694            [
 6695                ("editor1", Event::Edited),
 6696                ("editor1", Event::BufferEdited),
 6697                ("editor2", Event::BufferEdited),
 6698                ("editor1", Event::DirtyChanged),
 6699                ("editor2", Event::DirtyChanged)
 6700            ]
 6701        );
 6702
 6703        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6704        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6705        assert_eq!(
 6706            mem::take(&mut *events.borrow_mut()),
 6707            [
 6708                ("editor2", Event::Edited),
 6709                ("editor1", Event::BufferEdited),
 6710                ("editor2", Event::BufferEdited),
 6711            ]
 6712        );
 6713
 6714        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6715        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6716        assert_eq!(
 6717            mem::take(&mut *events.borrow_mut()),
 6718            [
 6719                ("editor1", Event::Edited),
 6720                ("editor1", Event::BufferEdited),
 6721                ("editor2", Event::BufferEdited),
 6722                ("editor1", Event::DirtyChanged),
 6723                ("editor2", Event::DirtyChanged),
 6724            ]
 6725        );
 6726
 6727        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6728        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6729        assert_eq!(
 6730            mem::take(&mut *events.borrow_mut()),
 6731            [
 6732                ("editor1", Event::Edited),
 6733                ("editor1", Event::BufferEdited),
 6734                ("editor2", Event::BufferEdited),
 6735                ("editor1", Event::DirtyChanged),
 6736                ("editor2", Event::DirtyChanged),
 6737            ]
 6738        );
 6739
 6740        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6741        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6742        assert_eq!(
 6743            mem::take(&mut *events.borrow_mut()),
 6744            [
 6745                ("editor2", Event::Edited),
 6746                ("editor1", Event::BufferEdited),
 6747                ("editor2", Event::BufferEdited),
 6748                ("editor1", Event::DirtyChanged),
 6749                ("editor2", Event::DirtyChanged),
 6750            ]
 6751        );
 6752
 6753        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6754        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6755        assert_eq!(
 6756            mem::take(&mut *events.borrow_mut()),
 6757            [
 6758                ("editor2", Event::Edited),
 6759                ("editor1", Event::BufferEdited),
 6760                ("editor2", Event::BufferEdited),
 6761                ("editor1", Event::DirtyChanged),
 6762                ("editor2", Event::DirtyChanged),
 6763            ]
 6764        );
 6765
 6766        // No event is emitted when the mutation is a no-op.
 6767        editor2.update(cx, |editor, cx| {
 6768            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6769
 6770            editor.backspace(&Backspace, cx);
 6771        });
 6772        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6773    }
 6774
 6775    #[gpui::test]
 6776    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6777        cx.set_global(Settings::test(cx));
 6778        let mut now = Instant::now();
 6779        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6780        let group_interval = buffer.read(cx).transaction_group_interval();
 6781        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6782        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6783
 6784        editor.update(cx, |editor, cx| {
 6785            editor.start_transaction_at(now, cx);
 6786            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6787
 6788            editor.insert("cd", cx);
 6789            editor.end_transaction_at(now, cx);
 6790            assert_eq!(editor.text(cx), "12cd56");
 6791            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6792
 6793            editor.start_transaction_at(now, cx);
 6794            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6795            editor.insert("e", cx);
 6796            editor.end_transaction_at(now, cx);
 6797            assert_eq!(editor.text(cx), "12cde6");
 6798            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6799
 6800            now += group_interval + Duration::from_millis(1);
 6801            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6802
 6803            // Simulate an edit in another editor
 6804            buffer.update(cx, |buffer, cx| {
 6805                buffer.start_transaction_at(now, cx);
 6806                buffer.edit([(0..1, "a")], None, cx);
 6807                buffer.edit([(1..1, "b")], None, cx);
 6808                buffer.end_transaction_at(now, cx);
 6809            });
 6810
 6811            assert_eq!(editor.text(cx), "ab2cde6");
 6812            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6813
 6814            // Last transaction happened past the group interval in a different editor.
 6815            // Undo it individually and don't restore selections.
 6816            editor.undo(&Undo, cx);
 6817            assert_eq!(editor.text(cx), "12cde6");
 6818            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6819
 6820            // First two transactions happened within the group interval in this editor.
 6821            // Undo them together and restore selections.
 6822            editor.undo(&Undo, cx);
 6823            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6824            assert_eq!(editor.text(cx), "123456");
 6825            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6826
 6827            // Redo the first two transactions together.
 6828            editor.redo(&Redo, cx);
 6829            assert_eq!(editor.text(cx), "12cde6");
 6830            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6831
 6832            // Redo the last transaction on its own.
 6833            editor.redo(&Redo, cx);
 6834            assert_eq!(editor.text(cx), "ab2cde6");
 6835            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6836
 6837            // Test empty transactions.
 6838            editor.start_transaction_at(now, cx);
 6839            editor.end_transaction_at(now, cx);
 6840            editor.undo(&Undo, cx);
 6841            assert_eq!(editor.text(cx), "12cde6");
 6842        });
 6843    }
 6844
 6845    #[gpui::test]
 6846    fn test_ime_composition(cx: &mut MutableAppContext) {
 6847        cx.set_global(Settings::test(cx));
 6848        let buffer = cx.add_model(|cx| {
 6849            let mut buffer = language::Buffer::new(0, "abcde", cx);
 6850            // Ensure automatic grouping doesn't occur.
 6851            buffer.set_group_interval(Duration::ZERO);
 6852            buffer
 6853        });
 6854
 6855        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6856        cx.add_window(Default::default(), |cx| {
 6857            let mut editor = build_editor(buffer.clone(), cx);
 6858
 6859            // Start a new IME composition.
 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            editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
 6863            assert_eq!(editor.text(cx), "äbcde");
 6864            assert_eq!(
 6865                editor.marked_text_ranges(cx),
 6866                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6867            );
 6868
 6869            // Finalize IME composition.
 6870            editor.replace_text_in_range(None, "ā", cx);
 6871            assert_eq!(editor.text(cx), "ābcde");
 6872            assert_eq!(editor.marked_text_ranges(cx), None);
 6873
 6874            // IME composition edits are grouped and are undone/redone at once.
 6875            editor.undo(&Default::default(), cx);
 6876            assert_eq!(editor.text(cx), "abcde");
 6877            assert_eq!(editor.marked_text_ranges(cx), None);
 6878            editor.redo(&Default::default(), cx);
 6879            assert_eq!(editor.text(cx), "ābcde");
 6880            assert_eq!(editor.marked_text_ranges(cx), None);
 6881
 6882            // Start a new IME composition.
 6883            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6884            assert_eq!(
 6885                editor.marked_text_ranges(cx),
 6886                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6887            );
 6888
 6889            // Undoing during an IME composition cancels it.
 6890            editor.undo(&Default::default(), cx);
 6891            assert_eq!(editor.text(cx), "ābcde");
 6892            assert_eq!(editor.marked_text_ranges(cx), None);
 6893
 6894            // Start a new IME composition with an invalid marked range, ensuring it gets clipped.
 6895            editor.replace_and_mark_text_in_range(Some(4..999), "è", None, cx);
 6896            assert_eq!(editor.text(cx), "ābcdè");
 6897            assert_eq!(
 6898                editor.marked_text_ranges(cx),
 6899                Some(vec![OffsetUtf16(4)..OffsetUtf16(5)])
 6900            );
 6901
 6902            // Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
 6903            editor.replace_text_in_range(Some(4..999), "ę", cx);
 6904            assert_eq!(editor.text(cx), "ābcdę");
 6905            assert_eq!(editor.marked_text_ranges(cx), None);
 6906
 6907            // Start a new IME composition with multiple cursors.
 6908            editor.change_selections(None, cx, |s| {
 6909                s.select_ranges([
 6910                    OffsetUtf16(1)..OffsetUtf16(1),
 6911                    OffsetUtf16(3)..OffsetUtf16(3),
 6912                    OffsetUtf16(5)..OffsetUtf16(5),
 6913                ])
 6914            });
 6915            editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, cx);
 6916            assert_eq!(editor.text(cx), "XYZbXYZdXYZ");
 6917            assert_eq!(
 6918                editor.marked_text_ranges(cx),
 6919                Some(vec![
 6920                    OffsetUtf16(0)..OffsetUtf16(3),
 6921                    OffsetUtf16(4)..OffsetUtf16(7),
 6922                    OffsetUtf16(8)..OffsetUtf16(11)
 6923                ])
 6924            );
 6925
 6926            // Ensure the newly-marked range gets treated as relative to the previously-marked ranges.
 6927            editor.replace_and_mark_text_in_range(Some(1..2), "1", None, cx);
 6928            assert_eq!(editor.text(cx), "X1ZbX1ZdX1Z");
 6929            assert_eq!(
 6930                editor.marked_text_ranges(cx),
 6931                Some(vec![
 6932                    OffsetUtf16(1)..OffsetUtf16(2),
 6933                    OffsetUtf16(5)..OffsetUtf16(6),
 6934                    OffsetUtf16(9)..OffsetUtf16(10)
 6935                ])
 6936            );
 6937
 6938            // Finalize IME composition with multiple cursors.
 6939            editor.replace_text_in_range(Some(9..10), "2", cx);
 6940            assert_eq!(editor.text(cx), "X2ZbX2ZdX2Z");
 6941            assert_eq!(editor.marked_text_ranges(cx), None);
 6942
 6943            editor
 6944        });
 6945    }
 6946
 6947    #[gpui::test]
 6948    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6949        cx.set_global(Settings::test(cx));
 6950
 6951        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6952        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6953        editor.update(cx, |view, cx| {
 6954            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6955        });
 6956        assert_eq!(
 6957            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6958            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6959        );
 6960
 6961        editor.update(cx, |view, cx| {
 6962            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6963        });
 6964
 6965        assert_eq!(
 6966            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6967            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6968        );
 6969
 6970        editor.update(cx, |view, cx| {
 6971            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6972        });
 6973
 6974        assert_eq!(
 6975            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6976            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6977        );
 6978
 6979        editor.update(cx, |view, cx| {
 6980            view.end_selection(cx);
 6981            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6982        });
 6983
 6984        assert_eq!(
 6985            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6986            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6987        );
 6988
 6989        editor.update(cx, |view, cx| {
 6990            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6991            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6992        });
 6993
 6994        assert_eq!(
 6995            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6996            [
 6997                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6998                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6999            ]
 7000        );
 7001
 7002        editor.update(cx, |view, cx| {
 7003            view.end_selection(cx);
 7004        });
 7005
 7006        assert_eq!(
 7007            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7008            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 7009        );
 7010    }
 7011
 7012    #[gpui::test]
 7013    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 7014        cx.set_global(Settings::test(cx));
 7015        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7016        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7017
 7018        view.update(cx, |view, cx| {
 7019            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 7020            assert_eq!(
 7021                view.selections.display_ranges(cx),
 7022                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 7023            );
 7024        });
 7025
 7026        view.update(cx, |view, cx| {
 7027            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7028            assert_eq!(
 7029                view.selections.display_ranges(cx),
 7030                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7031            );
 7032        });
 7033
 7034        view.update(cx, |view, cx| {
 7035            view.cancel(&Cancel, cx);
 7036            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7037            assert_eq!(
 7038                view.selections.display_ranges(cx),
 7039                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7040            );
 7041        });
 7042    }
 7043
 7044    #[gpui::test]
 7045    fn test_clone(cx: &mut gpui::MutableAppContext) {
 7046        let (text, selection_ranges) = marked_text_ranges(
 7047            indoc! {"
 7048                one
 7049                two
 7050                threeˇ
 7051                four
 7052                fiveˇ
 7053            "},
 7054            true,
 7055        );
 7056        cx.set_global(Settings::test(cx));
 7057        let buffer = MultiBuffer::build_simple(&text, cx);
 7058
 7059        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7060
 7061        editor.update(cx, |editor, cx| {
 7062            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 7063            editor.fold_ranges(
 7064                [
 7065                    Point::new(1, 0)..Point::new(2, 0),
 7066                    Point::new(3, 0)..Point::new(4, 0),
 7067                ],
 7068                cx,
 7069            );
 7070        });
 7071
 7072        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 7073            cx.add_window(Default::default(), |cx| editor.clone(cx))
 7074        });
 7075
 7076        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 7077        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 7078
 7079        assert_eq!(
 7080            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 7081            editor.update(cx, |e, cx| e.display_text(cx))
 7082        );
 7083        assert_eq!(
 7084            cloned_snapshot
 7085                .folds_in_range(0..text.len())
 7086                .collect::<Vec<_>>(),
 7087            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 7088        );
 7089        assert_set_eq!(
 7090            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 7091            editor.read(cx).selections.ranges(cx)
 7092        );
 7093        assert_set_eq!(
 7094            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 7095            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 7096        );
 7097    }
 7098
 7099    #[gpui::test]
 7100    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 7101        cx.set_global(Settings::test(cx));
 7102        use workspace::Item;
 7103        let (_, pane) = cx.add_window(Default::default(), |cx| Pane::new(None, cx));
 7104        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 7105
 7106        cx.add_view(&pane, |cx| {
 7107            let mut editor = build_editor(buffer.clone(), cx);
 7108            let handle = cx.handle();
 7109            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 7110
 7111            fn pop_history(
 7112                editor: &mut Editor,
 7113                cx: &mut MutableAppContext,
 7114            ) -> Option<NavigationEntry> {
 7115                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 7116            }
 7117
 7118            // Move the cursor a small distance.
 7119            // Nothing is added to the navigation history.
 7120            editor.change_selections(None, cx, |s| {
 7121                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 7122            });
 7123            editor.change_selections(None, cx, |s| {
 7124                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 7125            });
 7126            assert!(pop_history(&mut editor, cx).is_none());
 7127
 7128            // Move the cursor a large distance.
 7129            // The history can jump back to the previous position.
 7130            editor.change_selections(None, cx, |s| {
 7131                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 7132            });
 7133            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7134            editor.navigate(nav_entry.data.unwrap(), cx);
 7135            assert_eq!(nav_entry.item.id(), cx.view_id());
 7136            assert_eq!(
 7137                editor.selections.display_ranges(cx),
 7138                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 7139            );
 7140            assert!(pop_history(&mut editor, cx).is_none());
 7141
 7142            // Move the cursor a small distance via the mouse.
 7143            // Nothing is added to the navigation history.
 7144            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 7145            editor.end_selection(cx);
 7146            assert_eq!(
 7147                editor.selections.display_ranges(cx),
 7148                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7149            );
 7150            assert!(pop_history(&mut editor, cx).is_none());
 7151
 7152            // Move the cursor a large distance via the mouse.
 7153            // The history can jump back to the previous position.
 7154            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 7155            editor.end_selection(cx);
 7156            assert_eq!(
 7157                editor.selections.display_ranges(cx),
 7158                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 7159            );
 7160            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7161            editor.navigate(nav_entry.data.unwrap(), cx);
 7162            assert_eq!(nav_entry.item.id(), cx.view_id());
 7163            assert_eq!(
 7164                editor.selections.display_ranges(cx),
 7165                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7166            );
 7167            assert!(pop_history(&mut editor, cx).is_none());
 7168
 7169            // Set scroll position to check later
 7170            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 7171            let original_scroll_position = editor.scroll_position;
 7172            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 7173
 7174            // Jump to the end of the document and adjust scroll
 7175            editor.move_to_end(&MoveToEnd, cx);
 7176            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 7177            assert_ne!(editor.scroll_position, original_scroll_position);
 7178            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7179
 7180            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7181            editor.navigate(nav_entry.data.unwrap(), cx);
 7182            assert_eq!(editor.scroll_position, original_scroll_position);
 7183            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7184
 7185            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 7186            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 7187            invalid_anchor.text_anchor.buffer_id = Some(999);
 7188            let invalid_point = Point::new(9999, 0);
 7189            editor.navigate(
 7190                Box::new(NavigationData {
 7191                    cursor_anchor: invalid_anchor.clone(),
 7192                    cursor_position: invalid_point,
 7193                    scroll_top_anchor: invalid_anchor,
 7194                    scroll_top_row: invalid_point.row,
 7195                    scroll_position: Default::default(),
 7196                }),
 7197                cx,
 7198            );
 7199            assert_eq!(
 7200                editor.selections.display_ranges(cx),
 7201                &[editor.max_point(cx)..editor.max_point(cx)]
 7202            );
 7203            assert_eq!(
 7204                editor.scroll_position(cx),
 7205                vec2f(0., editor.max_point(cx).row() as f32)
 7206            );
 7207
 7208            editor
 7209        });
 7210    }
 7211
 7212    #[gpui::test]
 7213    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 7214        cx.set_global(Settings::test(cx));
 7215        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7216        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7217
 7218        view.update(cx, |view, cx| {
 7219            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 7220            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7221            view.end_selection(cx);
 7222
 7223            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 7224            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 7225            view.end_selection(cx);
 7226            assert_eq!(
 7227                view.selections.display_ranges(cx),
 7228                [
 7229                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 7230                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 7231                ]
 7232            );
 7233        });
 7234
 7235        view.update(cx, |view, cx| {
 7236            view.cancel(&Cancel, cx);
 7237            assert_eq!(
 7238                view.selections.display_ranges(cx),
 7239                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 7240            );
 7241        });
 7242
 7243        view.update(cx, |view, cx| {
 7244            view.cancel(&Cancel, cx);
 7245            assert_eq!(
 7246                view.selections.display_ranges(cx),
 7247                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 7248            );
 7249        });
 7250    }
 7251
 7252    #[gpui::test]
 7253    fn test_fold(cx: &mut gpui::MutableAppContext) {
 7254        cx.set_global(Settings::test(cx));
 7255        let buffer = MultiBuffer::build_simple(
 7256            &"
 7257                impl Foo {
 7258                    // Hello!
 7259
 7260                    fn a() {
 7261                        1
 7262                    }
 7263
 7264                    fn b() {
 7265                        2
 7266                    }
 7267
 7268                    fn c() {
 7269                        3
 7270                    }
 7271                }
 7272            "
 7273            .unindent(),
 7274            cx,
 7275        );
 7276        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7277
 7278        view.update(cx, |view, cx| {
 7279            view.change_selections(None, cx, |s| {
 7280                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 7281            });
 7282            view.fold(&Fold, cx);
 7283            assert_eq!(
 7284                view.display_text(cx),
 7285                "
 7286                    impl Foo {
 7287                        // Hello!
 7288
 7289                        fn a() {
 7290                            1
 7291                        }
 7292
 7293                        fn b() {…
 7294                        }
 7295
 7296                        fn c() {…
 7297                        }
 7298                    }
 7299                "
 7300                .unindent(),
 7301            );
 7302
 7303            view.fold(&Fold, cx);
 7304            assert_eq!(
 7305                view.display_text(cx),
 7306                "
 7307                    impl Foo {…
 7308                    }
 7309                "
 7310                .unindent(),
 7311            );
 7312
 7313            view.unfold_lines(&UnfoldLines, cx);
 7314            assert_eq!(
 7315                view.display_text(cx),
 7316                "
 7317                    impl Foo {
 7318                        // Hello!
 7319
 7320                        fn a() {
 7321                            1
 7322                        }
 7323
 7324                        fn b() {…
 7325                        }
 7326
 7327                        fn c() {…
 7328                        }
 7329                    }
 7330                "
 7331                .unindent(),
 7332            );
 7333
 7334            view.unfold_lines(&UnfoldLines, cx);
 7335            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7336        });
 7337    }
 7338
 7339    #[gpui::test]
 7340    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7341        cx.set_global(Settings::test(cx));
 7342        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7343        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7344
 7345        buffer.update(cx, |buffer, cx| {
 7346            buffer.edit(
 7347                vec![
 7348                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7349                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7350                ],
 7351                None,
 7352                cx,
 7353            );
 7354        });
 7355
 7356        view.update(cx, |view, cx| {
 7357            assert_eq!(
 7358                view.selections.display_ranges(cx),
 7359                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7360            );
 7361
 7362            view.move_down(&MoveDown, cx);
 7363            assert_eq!(
 7364                view.selections.display_ranges(cx),
 7365                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7366            );
 7367
 7368            view.move_right(&MoveRight, cx);
 7369            assert_eq!(
 7370                view.selections.display_ranges(cx),
 7371                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7372            );
 7373
 7374            view.move_left(&MoveLeft, cx);
 7375            assert_eq!(
 7376                view.selections.display_ranges(cx),
 7377                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7378            );
 7379
 7380            view.move_up(&MoveUp, cx);
 7381            assert_eq!(
 7382                view.selections.display_ranges(cx),
 7383                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7384            );
 7385
 7386            view.move_to_end(&MoveToEnd, cx);
 7387            assert_eq!(
 7388                view.selections.display_ranges(cx),
 7389                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7390            );
 7391
 7392            view.move_to_beginning(&MoveToBeginning, cx);
 7393            assert_eq!(
 7394                view.selections.display_ranges(cx),
 7395                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7396            );
 7397
 7398            view.change_selections(None, cx, |s| {
 7399                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 7400            });
 7401            view.select_to_beginning(&SelectToBeginning, cx);
 7402            assert_eq!(
 7403                view.selections.display_ranges(cx),
 7404                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7405            );
 7406
 7407            view.select_to_end(&SelectToEnd, cx);
 7408            assert_eq!(
 7409                view.selections.display_ranges(cx),
 7410                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7411            );
 7412        });
 7413    }
 7414
 7415    #[gpui::test]
 7416    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7417        cx.set_global(Settings::test(cx));
 7418        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7419        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7420
 7421        assert_eq!('ⓐ'.len_utf8(), 3);
 7422        assert_eq!('α'.len_utf8(), 2);
 7423
 7424        view.update(cx, |view, cx| {
 7425            view.fold_ranges(
 7426                vec![
 7427                    Point::new(0, 6)..Point::new(0, 12),
 7428                    Point::new(1, 2)..Point::new(1, 4),
 7429                    Point::new(2, 4)..Point::new(2, 8),
 7430                ],
 7431                cx,
 7432            );
 7433            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7434
 7435            view.move_right(&MoveRight, cx);
 7436            assert_eq!(
 7437                view.selections.display_ranges(cx),
 7438                &[empty_range(0, "".len())]
 7439            );
 7440            view.move_right(&MoveRight, cx);
 7441            assert_eq!(
 7442                view.selections.display_ranges(cx),
 7443                &[empty_range(0, "ⓐⓑ".len())]
 7444            );
 7445            view.move_right(&MoveRight, cx);
 7446            assert_eq!(
 7447                view.selections.display_ranges(cx),
 7448                &[empty_range(0, "ⓐⓑ…".len())]
 7449            );
 7450
 7451            view.move_down(&MoveDown, cx);
 7452            assert_eq!(
 7453                view.selections.display_ranges(cx),
 7454                &[empty_range(1, "ab…".len())]
 7455            );
 7456            view.move_left(&MoveLeft, cx);
 7457            assert_eq!(
 7458                view.selections.display_ranges(cx),
 7459                &[empty_range(1, "ab".len())]
 7460            );
 7461            view.move_left(&MoveLeft, cx);
 7462            assert_eq!(
 7463                view.selections.display_ranges(cx),
 7464                &[empty_range(1, "a".len())]
 7465            );
 7466
 7467            view.move_down(&MoveDown, cx);
 7468            assert_eq!(
 7469                view.selections.display_ranges(cx),
 7470                &[empty_range(2, "α".len())]
 7471            );
 7472            view.move_right(&MoveRight, cx);
 7473            assert_eq!(
 7474                view.selections.display_ranges(cx),
 7475                &[empty_range(2, "αβ".len())]
 7476            );
 7477            view.move_right(&MoveRight, cx);
 7478            assert_eq!(
 7479                view.selections.display_ranges(cx),
 7480                &[empty_range(2, "αβ…".len())]
 7481            );
 7482            view.move_right(&MoveRight, cx);
 7483            assert_eq!(
 7484                view.selections.display_ranges(cx),
 7485                &[empty_range(2, "αβ…ε".len())]
 7486            );
 7487
 7488            view.move_up(&MoveUp, cx);
 7489            assert_eq!(
 7490                view.selections.display_ranges(cx),
 7491                &[empty_range(1, "ab…e".len())]
 7492            );
 7493            view.move_up(&MoveUp, cx);
 7494            assert_eq!(
 7495                view.selections.display_ranges(cx),
 7496                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7497            );
 7498            view.move_left(&MoveLeft, cx);
 7499            assert_eq!(
 7500                view.selections.display_ranges(cx),
 7501                &[empty_range(0, "ⓐⓑ…".len())]
 7502            );
 7503            view.move_left(&MoveLeft, cx);
 7504            assert_eq!(
 7505                view.selections.display_ranges(cx),
 7506                &[empty_range(0, "ⓐⓑ".len())]
 7507            );
 7508            view.move_left(&MoveLeft, cx);
 7509            assert_eq!(
 7510                view.selections.display_ranges(cx),
 7511                &[empty_range(0, "".len())]
 7512            );
 7513        });
 7514    }
 7515
 7516    #[gpui::test]
 7517    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7518        cx.set_global(Settings::test(cx));
 7519        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7520        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7521        view.update(cx, |view, cx| {
 7522            view.change_selections(None, cx, |s| {
 7523                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7524            });
 7525            view.move_down(&MoveDown, cx);
 7526            assert_eq!(
 7527                view.selections.display_ranges(cx),
 7528                &[empty_range(1, "abcd".len())]
 7529            );
 7530
 7531            view.move_down(&MoveDown, cx);
 7532            assert_eq!(
 7533                view.selections.display_ranges(cx),
 7534                &[empty_range(2, "αβγ".len())]
 7535            );
 7536
 7537            view.move_down(&MoveDown, cx);
 7538            assert_eq!(
 7539                view.selections.display_ranges(cx),
 7540                &[empty_range(3, "abcd".len())]
 7541            );
 7542
 7543            view.move_down(&MoveDown, cx);
 7544            assert_eq!(
 7545                view.selections.display_ranges(cx),
 7546                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7547            );
 7548
 7549            view.move_up(&MoveUp, cx);
 7550            assert_eq!(
 7551                view.selections.display_ranges(cx),
 7552                &[empty_range(3, "abcd".len())]
 7553            );
 7554
 7555            view.move_up(&MoveUp, cx);
 7556            assert_eq!(
 7557                view.selections.display_ranges(cx),
 7558                &[empty_range(2, "αβγ".len())]
 7559            );
 7560        });
 7561    }
 7562
 7563    #[gpui::test]
 7564    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7565        cx.set_global(Settings::test(cx));
 7566        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7567        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7568        view.update(cx, |view, cx| {
 7569            view.change_selections(None, cx, |s| {
 7570                s.select_display_ranges([
 7571                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7572                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7573                ]);
 7574            });
 7575        });
 7576
 7577        view.update(cx, |view, cx| {
 7578            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7579            assert_eq!(
 7580                view.selections.display_ranges(cx),
 7581                &[
 7582                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7583                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7584                ]
 7585            );
 7586        });
 7587
 7588        view.update(cx, |view, cx| {
 7589            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7590            assert_eq!(
 7591                view.selections.display_ranges(cx),
 7592                &[
 7593                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7594                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7595                ]
 7596            );
 7597        });
 7598
 7599        view.update(cx, |view, cx| {
 7600            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7601            assert_eq!(
 7602                view.selections.display_ranges(cx),
 7603                &[
 7604                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7605                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7606                ]
 7607            );
 7608        });
 7609
 7610        view.update(cx, |view, cx| {
 7611            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7612            assert_eq!(
 7613                view.selections.display_ranges(cx),
 7614                &[
 7615                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7616                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7617                ]
 7618            );
 7619        });
 7620
 7621        // Moving to the end of line again is a no-op.
 7622        view.update(cx, |view, cx| {
 7623            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7624            assert_eq!(
 7625                view.selections.display_ranges(cx),
 7626                &[
 7627                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7628                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7629                ]
 7630            );
 7631        });
 7632
 7633        view.update(cx, |view, cx| {
 7634            view.move_left(&MoveLeft, cx);
 7635            view.select_to_beginning_of_line(
 7636                &SelectToBeginningOfLine {
 7637                    stop_at_soft_wraps: true,
 7638                },
 7639                cx,
 7640            );
 7641            assert_eq!(
 7642                view.selections.display_ranges(cx),
 7643                &[
 7644                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7645                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7646                ]
 7647            );
 7648        });
 7649
 7650        view.update(cx, |view, cx| {
 7651            view.select_to_beginning_of_line(
 7652                &SelectToBeginningOfLine {
 7653                    stop_at_soft_wraps: true,
 7654                },
 7655                cx,
 7656            );
 7657            assert_eq!(
 7658                view.selections.display_ranges(cx),
 7659                &[
 7660                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7661                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7662                ]
 7663            );
 7664        });
 7665
 7666        view.update(cx, |view, cx| {
 7667            view.select_to_beginning_of_line(
 7668                &SelectToBeginningOfLine {
 7669                    stop_at_soft_wraps: true,
 7670                },
 7671                cx,
 7672            );
 7673            assert_eq!(
 7674                view.selections.display_ranges(cx),
 7675                &[
 7676                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7677                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7678                ]
 7679            );
 7680        });
 7681
 7682        view.update(cx, |view, cx| {
 7683            view.select_to_end_of_line(
 7684                &SelectToEndOfLine {
 7685                    stop_at_soft_wraps: true,
 7686                },
 7687                cx,
 7688            );
 7689            assert_eq!(
 7690                view.selections.display_ranges(cx),
 7691                &[
 7692                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7693                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7694                ]
 7695            );
 7696        });
 7697
 7698        view.update(cx, |view, cx| {
 7699            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7700            assert_eq!(view.display_text(cx), "ab\n  de");
 7701            assert_eq!(
 7702                view.selections.display_ranges(cx),
 7703                &[
 7704                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7705                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7706                ]
 7707            );
 7708        });
 7709
 7710        view.update(cx, |view, cx| {
 7711            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7712            assert_eq!(view.display_text(cx), "\n");
 7713            assert_eq!(
 7714                view.selections.display_ranges(cx),
 7715                &[
 7716                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7717                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7718                ]
 7719            );
 7720        });
 7721    }
 7722
 7723    #[gpui::test]
 7724    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7725        cx.set_global(Settings::test(cx));
 7726        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7727        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7728        view.update(cx, |view, cx| {
 7729            view.change_selections(None, cx, |s| {
 7730                s.select_display_ranges([
 7731                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7732                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7733                ])
 7734            });
 7735
 7736            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7737            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7738
 7739            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7740            assert_selection_ranges("use stdˇ::str::{foo, bar}\n\n  ˇ{baz.qux()}", view, cx);
 7741
 7742            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7743            assert_selection_ranges("use ˇstd::str::{foo, bar}\n\nˇ  {baz.qux()}", view, cx);
 7744
 7745            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7746            assert_selection_ranges("ˇuse std::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7747
 7748            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7749            assert_selection_ranges("ˇuse std::str::{foo, barˇ}\n\n  {baz.qux()}", view, cx);
 7750
 7751            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7752            assert_selection_ranges("useˇ std::str::{foo, bar}ˇ\n\n  {baz.qux()}", view, cx);
 7753
 7754            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7755            assert_selection_ranges("use stdˇ::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7756
 7757            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7758            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7759
 7760            view.move_right(&MoveRight, cx);
 7761            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7762            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7763
 7764            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7765            assert_selection_ranges("use std«ˇ::s»tr::{foo, bar}\n\n  «ˇ{b»az.qux()}", view, cx);
 7766
 7767            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7768            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7769        });
 7770    }
 7771
 7772    #[gpui::test]
 7773    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7774        cx.set_global(Settings::test(cx));
 7775        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7776        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7777
 7778        view.update(cx, |view, cx| {
 7779            view.set_wrap_width(Some(140.), cx);
 7780            assert_eq!(
 7781                view.display_text(cx),
 7782                "use one::{\n    two::three::\n    four::five\n};"
 7783            );
 7784
 7785            view.change_selections(None, cx, |s| {
 7786                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7787            });
 7788
 7789            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7790            assert_eq!(
 7791                view.selections.display_ranges(cx),
 7792                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7793            );
 7794
 7795            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7796            assert_eq!(
 7797                view.selections.display_ranges(cx),
 7798                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7799            );
 7800
 7801            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7802            assert_eq!(
 7803                view.selections.display_ranges(cx),
 7804                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7805            );
 7806
 7807            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7808            assert_eq!(
 7809                view.selections.display_ranges(cx),
 7810                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7811            );
 7812
 7813            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7814            assert_eq!(
 7815                view.selections.display_ranges(cx),
 7816                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7817            );
 7818
 7819            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7820            assert_eq!(
 7821                view.selections.display_ranges(cx),
 7822                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7823            );
 7824        });
 7825    }
 7826
 7827    #[gpui::test]
 7828    async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) {
 7829        let mut cx = EditorTestContext::new(cx);
 7830        cx.set_state("one «two threeˇ» four");
 7831        cx.update_editor(|editor, cx| {
 7832            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7833            assert_eq!(editor.text(cx), " four");
 7834        });
 7835    }
 7836
 7837    #[gpui::test]
 7838    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7839        cx.set_global(Settings::test(cx));
 7840        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7841        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7842
 7843        view.update(cx, |view, cx| {
 7844            view.change_selections(None, cx, |s| {
 7845                s.select_display_ranges([
 7846                    // an empty selection - the preceding word fragment is deleted
 7847                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7848                    // characters selected - they are deleted
 7849                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7850                ])
 7851            });
 7852            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7853        });
 7854
 7855        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7856
 7857        view.update(cx, |view, cx| {
 7858            view.change_selections(None, cx, |s| {
 7859                s.select_display_ranges([
 7860                    // an empty selection - the following word fragment is deleted
 7861                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7862                    // characters selected - they are deleted
 7863                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7864                ])
 7865            });
 7866            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7867        });
 7868
 7869        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7870    }
 7871
 7872    #[gpui::test]
 7873    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7874        cx.set_global(Settings::test(cx));
 7875        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7876        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7877
 7878        view.update(cx, |view, cx| {
 7879            view.change_selections(None, cx, |s| {
 7880                s.select_display_ranges([
 7881                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7882                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7883                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7884                ])
 7885            });
 7886
 7887            view.newline(&Newline, cx);
 7888            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7889        });
 7890    }
 7891
 7892    #[gpui::test]
 7893    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7894        cx.set_global(Settings::test(cx));
 7895        let buffer = MultiBuffer::build_simple(
 7896            "
 7897                a
 7898                b(
 7899                    X
 7900                )
 7901                c(
 7902                    X
 7903                )
 7904            "
 7905            .unindent()
 7906            .as_str(),
 7907            cx,
 7908        );
 7909
 7910        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7911            let mut editor = build_editor(buffer.clone(), cx);
 7912            editor.change_selections(None, cx, |s| {
 7913                s.select_ranges([
 7914                    Point::new(2, 4)..Point::new(2, 5),
 7915                    Point::new(5, 4)..Point::new(5, 5),
 7916                ])
 7917            });
 7918            editor
 7919        });
 7920
 7921        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7922        buffer.update(cx, |buffer, cx| {
 7923            buffer.edit(
 7924                [
 7925                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7926                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7927                ],
 7928                None,
 7929                cx,
 7930            );
 7931            assert_eq!(
 7932                buffer.read(cx).text(),
 7933                "
 7934                    a
 7935                    b()
 7936                    c()
 7937                "
 7938                .unindent()
 7939            );
 7940        });
 7941
 7942        editor.update(cx, |editor, cx| {
 7943            assert_eq!(
 7944                editor.selections.ranges(cx),
 7945                &[
 7946                    Point::new(1, 2)..Point::new(1, 2),
 7947                    Point::new(2, 2)..Point::new(2, 2),
 7948                ],
 7949            );
 7950
 7951            editor.newline(&Newline, cx);
 7952            assert_eq!(
 7953                editor.text(cx),
 7954                "
 7955                    a
 7956                    b(
 7957                    )
 7958                    c(
 7959                    )
 7960                "
 7961                .unindent()
 7962            );
 7963
 7964            // The selections are moved after the inserted newlines
 7965            assert_eq!(
 7966                editor.selections.ranges(cx),
 7967                &[
 7968                    Point::new(2, 0)..Point::new(2, 0),
 7969                    Point::new(4, 0)..Point::new(4, 0),
 7970                ],
 7971            );
 7972        });
 7973    }
 7974
 7975    #[gpui::test]
 7976    async fn test_newline_below(cx: &mut gpui::TestAppContext) {
 7977        let mut cx = EditorTestContext::new(cx);
 7978        cx.update(|cx| {
 7979            cx.update_global::<Settings, _, _>(|settings, _| {
 7980                settings.editor_overrides.tab_size = Some(NonZeroU32::new(4).unwrap());
 7981            });
 7982        });
 7983
 7984        let language = Arc::new(
 7985            Language::new(
 7986                LanguageConfig::default(),
 7987                Some(tree_sitter_rust::language()),
 7988            )
 7989            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 7990            .unwrap(),
 7991        );
 7992        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 7993
 7994        cx.set_state(indoc! {"
 7995            const a: ˇA = (
 7996 7997                    «const_functionˇ»(ˇ),
 7998                    so«mˇ»et«hˇ»ing_ˇelse,ˇ
 7999 8000            ˇ);ˇ
 8001        "});
 8002        cx.update_editor(|e, cx| e.newline_below(&NewlineBelow, cx));
 8003        cx.assert_editor_state(indoc! {"
 8004            const a: A = (
 8005                ˇ
 8006                (
 8007                    ˇ
 8008                    const_function(),
 8009                    ˇ
 8010                    ˇ
 8011                    something_else,
 8012                    ˇ
 8013                    ˇ
 8014                    ˇ
 8015                    ˇ
 8016                )
 8017                ˇ
 8018            );
 8019            ˇ
 8020            ˇ
 8021        "});
 8022    }
 8023
 8024    #[gpui::test]
 8025    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 8026        cx.set_global(Settings::test(cx));
 8027        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 8028        let (_, editor) = cx.add_window(Default::default(), |cx| {
 8029            let mut editor = build_editor(buffer.clone(), cx);
 8030            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 8031            editor
 8032        });
 8033
 8034        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 8035        buffer.update(cx, |buffer, cx| {
 8036            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
 8037            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 8038        });
 8039
 8040        editor.update(cx, |editor, cx| {
 8041            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 8042
 8043            editor.insert("Z", cx);
 8044            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 8045
 8046            // The selections are moved after the inserted characters
 8047            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 8048        });
 8049    }
 8050
 8051    #[gpui::test]
 8052    async fn test_tab(cx: &mut gpui::TestAppContext) {
 8053        let mut cx = EditorTestContext::new(cx);
 8054        cx.update(|cx| {
 8055            cx.update_global::<Settings, _, _>(|settings, _| {
 8056                settings.editor_overrides.tab_size = Some(NonZeroU32::new(3).unwrap());
 8057            });
 8058        });
 8059        cx.set_state(indoc! {"
 8060            ˇabˇc
 8061            ˇ🏀ˇ🏀ˇefg
 8062 8063        "});
 8064        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8065        cx.assert_editor_state(indoc! {"
 8066              ˇab ˇc
 8067              ˇ🏀  ˇ🏀  ˇefg
 8068           d  ˇ
 8069        "});
 8070
 8071        cx.set_state(indoc! {"
 8072            a
 8073            «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8074        "});
 8075        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8076        cx.assert_editor_state(indoc! {"
 8077            a
 8078               «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8079        "});
 8080    }
 8081
 8082    #[gpui::test]
 8083    async fn test_tab_on_blank_line_auto_indents(cx: &mut gpui::TestAppContext) {
 8084        let mut cx = EditorTestContext::new(cx);
 8085        let language = Arc::new(
 8086            Language::new(
 8087                LanguageConfig::default(),
 8088                Some(tree_sitter_rust::language()),
 8089            )
 8090            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 8091            .unwrap(),
 8092        );
 8093        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8094
 8095        // cursors that are already at the suggested indent level insert
 8096        // a soft tab. cursors that are to the left of the suggested indent
 8097        // auto-indent their line.
 8098        cx.set_state(indoc! {"
 8099            ˇ
 8100            const a: B = (
 8101                c(
 8102                    d(
 8103            ˇ
 8104                    )
 8105            ˇ
 8106            ˇ    )
 8107            );
 8108        "});
 8109        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8110        cx.assert_editor_state(indoc! {"
 8111                ˇ
 8112            const a: B = (
 8113                c(
 8114                    d(
 8115                        ˇ
 8116                    )
 8117                    ˇ
 8118                ˇ)
 8119            );
 8120        "});
 8121
 8122        // handle auto-indent when there are multiple cursors on the same line
 8123        cx.set_state(indoc! {"
 8124            const a: B = (
 8125                c(
 8126            ˇ    ˇ    
 8127            ˇ    )
 8128            );
 8129        "});
 8130        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8131        cx.assert_editor_state(indoc! {"
 8132            const a: B = (
 8133                c(
 8134                    ˇ
 8135                ˇ)
 8136            );
 8137        "});
 8138    }
 8139
 8140    #[gpui::test]
 8141    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 8142        let mut cx = EditorTestContext::new(cx);
 8143
 8144        cx.set_state(indoc! {"
 8145              «oneˇ» «twoˇ»
 8146            three
 8147             four
 8148        "});
 8149        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8150        cx.assert_editor_state(indoc! {"
 8151                «oneˇ» «twoˇ»
 8152            three
 8153             four
 8154        "});
 8155
 8156        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8157        cx.assert_editor_state(indoc! {"
 8158            «oneˇ» «twoˇ»
 8159            three
 8160             four
 8161        "});
 8162
 8163        // select across line ending
 8164        cx.set_state(indoc! {"
 8165            one two
 8166            t«hree
 8167            ˇ» four
 8168        "});
 8169        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8170        cx.assert_editor_state(indoc! {"
 8171            one two
 8172                t«hree
 8173            ˇ» four
 8174        "});
 8175
 8176        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8177        cx.assert_editor_state(indoc! {"
 8178            one two
 8179            t«hree
 8180            ˇ» four
 8181        "});
 8182
 8183        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8184        cx.set_state(indoc! {"
 8185            one two
 8186            ˇthree
 8187                four
 8188        "});
 8189        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8190        cx.assert_editor_state(indoc! {"
 8191            one two
 8192                ˇthree
 8193                four
 8194        "});
 8195
 8196        cx.set_state(indoc! {"
 8197            one two
 8198            ˇ    three
 8199             four
 8200        "});
 8201        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8202        cx.assert_editor_state(indoc! {"
 8203            one two
 8204            ˇthree
 8205             four
 8206        "});
 8207    }
 8208
 8209    #[gpui::test]
 8210    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 8211        let mut cx = EditorTestContext::new(cx);
 8212        cx.update(|cx| {
 8213            cx.update_global::<Settings, _, _>(|settings, _| {
 8214                settings.editor_overrides.hard_tabs = Some(true);
 8215            });
 8216        });
 8217
 8218        // select two ranges on one line
 8219        cx.set_state(indoc! {"
 8220            «oneˇ» «twoˇ»
 8221            three
 8222            four
 8223        "});
 8224        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8225        cx.assert_editor_state(indoc! {"
 8226            \t«oneˇ» «twoˇ»
 8227            three
 8228            four
 8229        "});
 8230        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8231        cx.assert_editor_state(indoc! {"
 8232            \t\t«oneˇ» «twoˇ»
 8233            three
 8234            four
 8235        "});
 8236        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8237        cx.assert_editor_state(indoc! {"
 8238            \t«oneˇ» «twoˇ»
 8239            three
 8240            four
 8241        "});
 8242        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8243        cx.assert_editor_state(indoc! {"
 8244            «oneˇ» «twoˇ»
 8245            three
 8246            four
 8247        "});
 8248
 8249        // select across a line ending
 8250        cx.set_state(indoc! {"
 8251            one two
 8252            t«hree
 8253            ˇ»four
 8254        "});
 8255        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8256        cx.assert_editor_state(indoc! {"
 8257            one two
 8258            \tt«hree
 8259            ˇ»four
 8260        "});
 8261        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8262        cx.assert_editor_state(indoc! {"
 8263            one two
 8264            \t\tt«hree
 8265            ˇ»four
 8266        "});
 8267        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8268        cx.assert_editor_state(indoc! {"
 8269            one two
 8270            \tt«hree
 8271            ˇ»four
 8272        "});
 8273        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8274        cx.assert_editor_state(indoc! {"
 8275            one two
 8276            t«hree
 8277            ˇ»four
 8278        "});
 8279
 8280        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8281        cx.set_state(indoc! {"
 8282            one two
 8283            ˇthree
 8284            four
 8285        "});
 8286        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8287        cx.assert_editor_state(indoc! {"
 8288            one two
 8289            ˇthree
 8290            four
 8291        "});
 8292        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8293        cx.assert_editor_state(indoc! {"
 8294            one two
 8295            \tˇthree
 8296            four
 8297        "});
 8298        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8299        cx.assert_editor_state(indoc! {"
 8300            one two
 8301            ˇthree
 8302            four
 8303        "});
 8304    }
 8305
 8306    #[gpui::test]
 8307    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 8308        cx.set_global(
 8309            Settings::test(cx)
 8310                .with_language_defaults(
 8311                    "TOML",
 8312                    EditorSettings {
 8313                        tab_size: Some(2.try_into().unwrap()),
 8314                        ..Default::default()
 8315                    },
 8316                )
 8317                .with_language_defaults(
 8318                    "Rust",
 8319                    EditorSettings {
 8320                        tab_size: Some(4.try_into().unwrap()),
 8321                        ..Default::default()
 8322                    },
 8323                ),
 8324        );
 8325        let toml_language = Arc::new(Language::new(
 8326            LanguageConfig {
 8327                name: "TOML".into(),
 8328                ..Default::default()
 8329            },
 8330            None,
 8331        ));
 8332        let rust_language = Arc::new(Language::new(
 8333            LanguageConfig {
 8334                name: "Rust".into(),
 8335                ..Default::default()
 8336            },
 8337            None,
 8338        ));
 8339
 8340        let toml_buffer = cx
 8341            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 8342        let rust_buffer = cx.add_model(|cx| {
 8343            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 8344        });
 8345        let multibuffer = cx.add_model(|cx| {
 8346            let mut multibuffer = MultiBuffer::new(0);
 8347            multibuffer.push_excerpts(
 8348                toml_buffer.clone(),
 8349                [ExcerptRange {
 8350                    context: Point::new(0, 0)..Point::new(2, 0),
 8351                    primary: None,
 8352                }],
 8353                cx,
 8354            );
 8355            multibuffer.push_excerpts(
 8356                rust_buffer.clone(),
 8357                [ExcerptRange {
 8358                    context: Point::new(0, 0)..Point::new(1, 0),
 8359                    primary: None,
 8360                }],
 8361                cx,
 8362            );
 8363            multibuffer
 8364        });
 8365
 8366        cx.add_window(Default::default(), |cx| {
 8367            let mut editor = build_editor(multibuffer, cx);
 8368
 8369            assert_eq!(
 8370                editor.text(cx),
 8371                indoc! {"
 8372                    a = 1
 8373                    b = 2
 8374
 8375                    const c: usize = 3;
 8376                "}
 8377            );
 8378
 8379            select_ranges(
 8380                &mut editor,
 8381                indoc! {"
 8382                    «aˇ» = 1
 8383                    b = 2
 8384
 8385                    «const c:ˇ» usize = 3;
 8386                "},
 8387                cx,
 8388            );
 8389
 8390            editor.tab(&Tab, cx);
 8391            assert_text_with_selections(
 8392                &mut editor,
 8393                indoc! {"
 8394                      «aˇ» = 1
 8395                    b = 2
 8396
 8397                        «const c:ˇ» usize = 3;
 8398                "},
 8399                cx,
 8400            );
 8401            editor.tab_prev(&TabPrev, cx);
 8402            assert_text_with_selections(
 8403                &mut editor,
 8404                indoc! {"
 8405                    «aˇ» = 1
 8406                    b = 2
 8407
 8408                    «const c:ˇ» usize = 3;
 8409                "},
 8410                cx,
 8411            );
 8412
 8413            editor
 8414        });
 8415    }
 8416
 8417    #[gpui::test]
 8418    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 8419        let mut cx = EditorTestContext::new(cx);
 8420
 8421        // Basic backspace
 8422        cx.set_state(indoc! {"
 8423            onˇe two three
 8424            fou«rˇ» five six
 8425            seven «ˇeight nine
 8426            »ten
 8427        "});
 8428        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8429        cx.assert_editor_state(indoc! {"
 8430            oˇe two three
 8431            fouˇ five six
 8432            seven ˇten
 8433        "});
 8434
 8435        // Test backspace inside and around indents
 8436        cx.set_state(indoc! {"
 8437            zero
 8438                ˇone
 8439                    ˇtwo
 8440                ˇ ˇ ˇ  three
 8441            ˇ  ˇ  four
 8442        "});
 8443        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8444        cx.assert_editor_state(indoc! {"
 8445            zero
 8446            ˇone
 8447                ˇtwo
 8448            ˇ  threeˇ  four
 8449        "});
 8450
 8451        // Test backspace with line_mode set to true
 8452        cx.update_editor(|e, _| e.selections.line_mode = true);
 8453        cx.set_state(indoc! {"
 8454            The ˇquick ˇbrown
 8455            fox jumps over
 8456            the lazy dog
 8457            ˇThe qu«ick bˇ»rown"});
 8458        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8459        cx.assert_editor_state(indoc! {"
 8460            ˇfox jumps over
 8461            the lazy dogˇ"});
 8462    }
 8463
 8464    #[gpui::test]
 8465    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8466        let mut cx = EditorTestContext::new(cx);
 8467
 8468        cx.set_state(indoc! {"
 8469            onˇe two three
 8470            fou«rˇ» five six
 8471            seven «ˇeight nine
 8472            »ten
 8473        "});
 8474        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8475        cx.assert_editor_state(indoc! {"
 8476            onˇ two three
 8477            fouˇ five six
 8478            seven ˇten
 8479        "});
 8480
 8481        // Test backspace with line_mode set to true
 8482        cx.update_editor(|e, _| e.selections.line_mode = true);
 8483        cx.set_state(indoc! {"
 8484            The ˇquick ˇbrown
 8485            fox «ˇjum»ps over
 8486            the lazy dog
 8487            ˇThe qu«ick bˇ»rown"});
 8488        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8489        cx.assert_editor_state("ˇthe lazy dogˇ");
 8490    }
 8491
 8492    #[gpui::test]
 8493    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8494        cx.set_global(Settings::test(cx));
 8495        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8496        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8497        view.update(cx, |view, cx| {
 8498            view.change_selections(None, cx, |s| {
 8499                s.select_display_ranges([
 8500                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8501                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8502                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8503                ])
 8504            });
 8505            view.delete_line(&DeleteLine, cx);
 8506            assert_eq!(view.display_text(cx), "ghi");
 8507            assert_eq!(
 8508                view.selections.display_ranges(cx),
 8509                vec![
 8510                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8511                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8512                ]
 8513            );
 8514        });
 8515
 8516        cx.set_global(Settings::test(cx));
 8517        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8518        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8519        view.update(cx, |view, cx| {
 8520            view.change_selections(None, cx, |s| {
 8521                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8522            });
 8523            view.delete_line(&DeleteLine, cx);
 8524            assert_eq!(view.display_text(cx), "ghi\n");
 8525            assert_eq!(
 8526                view.selections.display_ranges(cx),
 8527                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8528            );
 8529        });
 8530    }
 8531
 8532    #[gpui::test]
 8533    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8534        cx.set_global(Settings::test(cx));
 8535        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8536        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8537        view.update(cx, |view, cx| {
 8538            view.change_selections(None, cx, |s| {
 8539                s.select_display_ranges([
 8540                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8541                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8542                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8543                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8544                ])
 8545            });
 8546            view.duplicate_line(&DuplicateLine, cx);
 8547            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8548            assert_eq!(
 8549                view.selections.display_ranges(cx),
 8550                vec![
 8551                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8552                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8553                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8554                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8555                ]
 8556            );
 8557        });
 8558
 8559        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8560        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8561        view.update(cx, |view, cx| {
 8562            view.change_selections(None, cx, |s| {
 8563                s.select_display_ranges([
 8564                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8565                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8566                ])
 8567            });
 8568            view.duplicate_line(&DuplicateLine, cx);
 8569            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8570            assert_eq!(
 8571                view.selections.display_ranges(cx),
 8572                vec![
 8573                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8574                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8575                ]
 8576            );
 8577        });
 8578    }
 8579
 8580    #[gpui::test]
 8581    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8582        cx.set_global(Settings::test(cx));
 8583        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8584        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8585        view.update(cx, |view, cx| {
 8586            view.fold_ranges(
 8587                vec![
 8588                    Point::new(0, 2)..Point::new(1, 2),
 8589                    Point::new(2, 3)..Point::new(4, 1),
 8590                    Point::new(7, 0)..Point::new(8, 4),
 8591                ],
 8592                cx,
 8593            );
 8594            view.change_selections(None, cx, |s| {
 8595                s.select_display_ranges([
 8596                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8597                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8598                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8599                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8600                ])
 8601            });
 8602            assert_eq!(
 8603                view.display_text(cx),
 8604                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8605            );
 8606
 8607            view.move_line_up(&MoveLineUp, cx);
 8608            assert_eq!(
 8609                view.display_text(cx),
 8610                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8611            );
 8612            assert_eq!(
 8613                view.selections.display_ranges(cx),
 8614                vec![
 8615                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8616                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8617                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8618                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8619                ]
 8620            );
 8621        });
 8622
 8623        view.update(cx, |view, cx| {
 8624            view.move_line_down(&MoveLineDown, cx);
 8625            assert_eq!(
 8626                view.display_text(cx),
 8627                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8628            );
 8629            assert_eq!(
 8630                view.selections.display_ranges(cx),
 8631                vec![
 8632                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8633                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8634                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8635                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8636                ]
 8637            );
 8638        });
 8639
 8640        view.update(cx, |view, cx| {
 8641            view.move_line_down(&MoveLineDown, cx);
 8642            assert_eq!(
 8643                view.display_text(cx),
 8644                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8645            );
 8646            assert_eq!(
 8647                view.selections.display_ranges(cx),
 8648                vec![
 8649                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8650                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8651                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8652                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8653                ]
 8654            );
 8655        });
 8656
 8657        view.update(cx, |view, cx| {
 8658            view.move_line_up(&MoveLineUp, cx);
 8659            assert_eq!(
 8660                view.display_text(cx),
 8661                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8662            );
 8663            assert_eq!(
 8664                view.selections.display_ranges(cx),
 8665                vec![
 8666                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8667                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8668                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8669                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8670                ]
 8671            );
 8672        });
 8673    }
 8674
 8675    #[gpui::test]
 8676    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8677        cx.set_global(Settings::test(cx));
 8678        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8679        let snapshot = buffer.read(cx).snapshot(cx);
 8680        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8681        editor.update(cx, |editor, cx| {
 8682            editor.insert_blocks(
 8683                [BlockProperties {
 8684                    style: BlockStyle::Fixed,
 8685                    position: snapshot.anchor_after(Point::new(2, 0)),
 8686                    disposition: BlockDisposition::Below,
 8687                    height: 1,
 8688                    render: Arc::new(|_| Empty::new().boxed()),
 8689                }],
 8690                cx,
 8691            );
 8692            editor.change_selections(None, cx, |s| {
 8693                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8694            });
 8695            editor.move_line_down(&MoveLineDown, cx);
 8696        });
 8697    }
 8698
 8699    #[gpui::test]
 8700    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8701        cx.set_global(Settings::test(cx));
 8702
 8703        _ = cx
 8704            .add_window(Default::default(), |cx| {
 8705                let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8706
 8707                editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8708                editor.transpose(&Default::default(), cx);
 8709                assert_eq!(editor.text(cx), "bac");
 8710                assert_eq!(editor.selections.ranges(cx), [2..2]);
 8711
 8712                editor.transpose(&Default::default(), cx);
 8713                assert_eq!(editor.text(cx), "bca");
 8714                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8715
 8716                editor.transpose(&Default::default(), cx);
 8717                assert_eq!(editor.text(cx), "bac");
 8718                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8719
 8720                editor
 8721            })
 8722            .1;
 8723
 8724        _ = cx
 8725            .add_window(Default::default(), |cx| {
 8726                let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8727
 8728                editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8729                editor.transpose(&Default::default(), cx);
 8730                assert_eq!(editor.text(cx), "acb\nde");
 8731                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8732
 8733                editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8734                editor.transpose(&Default::default(), cx);
 8735                assert_eq!(editor.text(cx), "acbd\ne");
 8736                assert_eq!(editor.selections.ranges(cx), [5..5]);
 8737
 8738                editor.transpose(&Default::default(), cx);
 8739                assert_eq!(editor.text(cx), "acbde\n");
 8740                assert_eq!(editor.selections.ranges(cx), [6..6]);
 8741
 8742                editor.transpose(&Default::default(), cx);
 8743                assert_eq!(editor.text(cx), "acbd\ne");
 8744                assert_eq!(editor.selections.ranges(cx), [6..6]);
 8745
 8746                editor
 8747            })
 8748            .1;
 8749
 8750        _ = cx
 8751            .add_window(Default::default(), |cx| {
 8752                let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8753
 8754                editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8755                editor.transpose(&Default::default(), cx);
 8756                assert_eq!(editor.text(cx), "bacd\ne");
 8757                assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8758
 8759                editor.transpose(&Default::default(), cx);
 8760                assert_eq!(editor.text(cx), "bcade\n");
 8761                assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8762
 8763                editor.transpose(&Default::default(), cx);
 8764                assert_eq!(editor.text(cx), "bcda\ne");
 8765                assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8766
 8767                editor.transpose(&Default::default(), cx);
 8768                assert_eq!(editor.text(cx), "bcade\n");
 8769                assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8770
 8771                editor.transpose(&Default::default(), cx);
 8772                assert_eq!(editor.text(cx), "bcaed\n");
 8773                assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8774
 8775                editor
 8776            })
 8777            .1;
 8778
 8779        _ = cx
 8780            .add_window(Default::default(), |cx| {
 8781                let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8782
 8783                editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8784                editor.transpose(&Default::default(), cx);
 8785                assert_eq!(editor.text(cx), "🏀🍐✋");
 8786                assert_eq!(editor.selections.ranges(cx), [8..8]);
 8787
 8788                editor.transpose(&Default::default(), cx);
 8789                assert_eq!(editor.text(cx), "🏀✋🍐");
 8790                assert_eq!(editor.selections.ranges(cx), [11..11]);
 8791
 8792                editor.transpose(&Default::default(), cx);
 8793                assert_eq!(editor.text(cx), "🏀🍐✋");
 8794                assert_eq!(editor.selections.ranges(cx), [11..11]);
 8795
 8796                editor
 8797            })
 8798            .1;
 8799    }
 8800
 8801    #[gpui::test]
 8802    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8803        let mut cx = EditorTestContext::new(cx);
 8804
 8805        cx.set_state("«one✅ ˇ»two «three ˇ»four «five ˇ»six ");
 8806        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8807        cx.assert_editor_state("ˇtwo ˇfour ˇsix ");
 8808
 8809        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8810        cx.set_state("two ˇfour ˇsix ˇ");
 8811        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8812        cx.assert_editor_state("two one✅ ˇfour three ˇsix five ˇ");
 8813
 8814        // Paste again but with only two cursors. Since the number of cursors doesn't
 8815        // match the number of slices in the clipboard, the entire clipboard text
 8816        // is pasted at each cursor.
 8817        cx.set_state("ˇtwo one✅ four three six five ˇ");
 8818        cx.update_editor(|e, cx| {
 8819            e.handle_input("( ", cx);
 8820            e.paste(&Paste, cx);
 8821            e.handle_input(") ", cx);
 8822        });
 8823        cx.assert_editor_state(indoc! {"
 8824            ( one✅ 
 8825            three 
 8826            five ) ˇtwo one✅ four three six five ( one✅ 
 8827            three 
 8828            five ) ˇ"});
 8829
 8830        // Cut with three selections, one of which is full-line.
 8831        cx.set_state(indoc! {"
 8832            1«2ˇ»3
 8833            4ˇ567
 8834            «8ˇ»9"});
 8835        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8836        cx.assert_editor_state(indoc! {"
 8837            1ˇ3
 8838            ˇ9"});
 8839
 8840        // Paste with three selections, noticing how the copied selection that was full-line
 8841        // gets inserted before the second cursor.
 8842        cx.set_state(indoc! {"
 8843            1ˇ3
 8844 8845            «oˇ»ne"});
 8846        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8847        cx.assert_editor_state(indoc! {"
 8848            12ˇ3
 8849            4567
 8850 8851            8ˇne"});
 8852
 8853        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8854        cx.set_state(indoc! {"
 8855            The quick brown
 8856            fox juˇmps over
 8857            the lazy dog"});
 8858        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8859        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8860
 8861        // Paste with three selections, noticing how the copied full-line selection is inserted
 8862        // before the empty selections but replaces the selection that is non-empty.
 8863        cx.set_state(indoc! {"
 8864            Tˇhe quick brown
 8865            «foˇ»x jumps over
 8866            tˇhe lazy dog"});
 8867        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8868        cx.assert_editor_state(indoc! {"
 8869            fox jumps over
 8870            Tˇhe quick brown
 8871            fox jumps over
 8872            ˇx jumps over
 8873            fox jumps over
 8874            tˇhe lazy dog"});
 8875    }
 8876
 8877    #[gpui::test]
 8878    async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
 8879        let mut cx = EditorTestContext::new(cx);
 8880        let language = Arc::new(Language::new(
 8881            LanguageConfig::default(),
 8882            Some(tree_sitter_rust::language()),
 8883        ));
 8884        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8885
 8886        // Cut an indented block, without the leading whitespace.
 8887        cx.set_state(indoc! {"
 8888            const a: B = (
 8889                c(),
 8890                «d(
 8891                    e,
 8892                    f
 8893                )ˇ»
 8894            );
 8895        "});
 8896        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8897        cx.assert_editor_state(indoc! {"
 8898            const a: B = (
 8899                c(),
 8900                ˇ
 8901            );
 8902        "});
 8903
 8904        // Paste it at the same position.
 8905        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8906        cx.assert_editor_state(indoc! {"
 8907            const a: B = (
 8908                c(),
 8909                d(
 8910                    e,
 8911                    f
 8912 8913            );
 8914        "});
 8915
 8916        // Paste it at a line with a lower indent level.
 8917        cx.set_state(indoc! {"
 8918            ˇ
 8919            const a: B = (
 8920                c(),
 8921            );
 8922        "});
 8923        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8924        cx.assert_editor_state(indoc! {"
 8925            d(
 8926                e,
 8927                f
 8928 8929            const a: B = (
 8930                c(),
 8931            );
 8932        "});
 8933
 8934        // Cut an indented block, with the leading whitespace.
 8935        cx.set_state(indoc! {"
 8936            const a: B = (
 8937                c(),
 8938            «    d(
 8939                    e,
 8940                    f
 8941                )
 8942            ˇ»);
 8943        "});
 8944        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8945        cx.assert_editor_state(indoc! {"
 8946            const a: B = (
 8947                c(),
 8948            ˇ);
 8949        "});
 8950
 8951        // Paste it at the same position.
 8952        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8953        cx.assert_editor_state(indoc! {"
 8954            const a: B = (
 8955                c(),
 8956                d(
 8957                    e,
 8958                    f
 8959                )
 8960            ˇ);
 8961        "});
 8962
 8963        // Paste it at a line with a higher indent level.
 8964        cx.set_state(indoc! {"
 8965            const a: B = (
 8966                c(),
 8967                d(
 8968                    e,
 8969 8970                )
 8971            );
 8972        "});
 8973        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8974        cx.assert_editor_state(indoc! {"
 8975            const a: B = (
 8976                c(),
 8977                d(
 8978                    e,
 8979                    f    d(
 8980                        e,
 8981                        f
 8982                    )
 8983            ˇ
 8984                )
 8985            );
 8986        "});
 8987    }
 8988
 8989    #[gpui::test]
 8990    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8991        cx.set_global(Settings::test(cx));
 8992        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8993        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8994        view.update(cx, |view, cx| {
 8995            view.select_all(&SelectAll, cx);
 8996            assert_eq!(
 8997                view.selections.display_ranges(cx),
 8998                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8999            );
 9000        });
 9001    }
 9002
 9003    #[gpui::test]
 9004    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 9005        cx.set_global(Settings::test(cx));
 9006        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 9007        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9008        view.update(cx, |view, cx| {
 9009            view.change_selections(None, cx, |s| {
 9010                s.select_display_ranges([
 9011                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9012                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9013                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9014                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 9015                ])
 9016            });
 9017            view.select_line(&SelectLine, cx);
 9018            assert_eq!(
 9019                view.selections.display_ranges(cx),
 9020                vec![
 9021                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 9022                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 9023                ]
 9024            );
 9025        });
 9026
 9027        view.update(cx, |view, cx| {
 9028            view.select_line(&SelectLine, cx);
 9029            assert_eq!(
 9030                view.selections.display_ranges(cx),
 9031                vec![
 9032                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 9033                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 9034                ]
 9035            );
 9036        });
 9037
 9038        view.update(cx, |view, cx| {
 9039            view.select_line(&SelectLine, cx);
 9040            assert_eq!(
 9041                view.selections.display_ranges(cx),
 9042                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 9043            );
 9044        });
 9045    }
 9046
 9047    #[gpui::test]
 9048    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 9049        cx.set_global(Settings::test(cx));
 9050        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 9051        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9052        view.update(cx, |view, cx| {
 9053            view.fold_ranges(
 9054                vec![
 9055                    Point::new(0, 2)..Point::new(1, 2),
 9056                    Point::new(2, 3)..Point::new(4, 1),
 9057                    Point::new(7, 0)..Point::new(8, 4),
 9058                ],
 9059                cx,
 9060            );
 9061            view.change_selections(None, cx, |s| {
 9062                s.select_display_ranges([
 9063                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9064                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9065                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9066                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9067                ])
 9068            });
 9069            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 9070        });
 9071
 9072        view.update(cx, |view, cx| {
 9073            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9074            assert_eq!(
 9075                view.display_text(cx),
 9076                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 9077            );
 9078            assert_eq!(
 9079                view.selections.display_ranges(cx),
 9080                [
 9081                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 9082                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9083                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 9084                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 9085                ]
 9086            );
 9087        });
 9088
 9089        view.update(cx, |view, cx| {
 9090            view.change_selections(None, cx, |s| {
 9091                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 9092            });
 9093            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9094            assert_eq!(
 9095                view.display_text(cx),
 9096                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 9097            );
 9098            assert_eq!(
 9099                view.selections.display_ranges(cx),
 9100                [
 9101                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 9102                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 9103                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9104                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 9105                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 9106                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 9107                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 9108                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 9109                ]
 9110            );
 9111        });
 9112    }
 9113
 9114    #[gpui::test]
 9115    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 9116        cx.set_global(Settings::test(cx));
 9117        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 9118        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9119
 9120        view.update(cx, |view, cx| {
 9121            view.change_selections(None, cx, |s| {
 9122                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 9123            });
 9124        });
 9125        view.update(cx, |view, cx| {
 9126            view.add_selection_above(&AddSelectionAbove, cx);
 9127            assert_eq!(
 9128                view.selections.display_ranges(cx),
 9129                vec![
 9130                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9131                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9132                ]
 9133            );
 9134        });
 9135
 9136        view.update(cx, |view, cx| {
 9137            view.add_selection_above(&AddSelectionAbove, cx);
 9138            assert_eq!(
 9139                view.selections.display_ranges(cx),
 9140                vec![
 9141                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9142                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9143                ]
 9144            );
 9145        });
 9146
 9147        view.update(cx, |view, cx| {
 9148            view.add_selection_below(&AddSelectionBelow, cx);
 9149            assert_eq!(
 9150                view.selections.display_ranges(cx),
 9151                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9152            );
 9153
 9154            view.undo_selection(&UndoSelection, cx);
 9155            assert_eq!(
 9156                view.selections.display_ranges(cx),
 9157                vec![
 9158                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9159                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9160                ]
 9161            );
 9162
 9163            view.redo_selection(&RedoSelection, cx);
 9164            assert_eq!(
 9165                view.selections.display_ranges(cx),
 9166                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9167            );
 9168        });
 9169
 9170        view.update(cx, |view, cx| {
 9171            view.add_selection_below(&AddSelectionBelow, cx);
 9172            assert_eq!(
 9173                view.selections.display_ranges(cx),
 9174                vec![
 9175                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9176                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9177                ]
 9178            );
 9179        });
 9180
 9181        view.update(cx, |view, cx| {
 9182            view.add_selection_below(&AddSelectionBelow, cx);
 9183            assert_eq!(
 9184                view.selections.display_ranges(cx),
 9185                vec![
 9186                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9187                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9188                ]
 9189            );
 9190        });
 9191
 9192        view.update(cx, |view, cx| {
 9193            view.change_selections(None, cx, |s| {
 9194                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 9195            });
 9196        });
 9197        view.update(cx, |view, cx| {
 9198            view.add_selection_below(&AddSelectionBelow, cx);
 9199            assert_eq!(
 9200                view.selections.display_ranges(cx),
 9201                vec![
 9202                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9203                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9204                ]
 9205            );
 9206        });
 9207
 9208        view.update(cx, |view, cx| {
 9209            view.add_selection_below(&AddSelectionBelow, cx);
 9210            assert_eq!(
 9211                view.selections.display_ranges(cx),
 9212                vec![
 9213                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9214                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9215                ]
 9216            );
 9217        });
 9218
 9219        view.update(cx, |view, cx| {
 9220            view.add_selection_above(&AddSelectionAbove, cx);
 9221            assert_eq!(
 9222                view.selections.display_ranges(cx),
 9223                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9224            );
 9225        });
 9226
 9227        view.update(cx, |view, cx| {
 9228            view.add_selection_above(&AddSelectionAbove, cx);
 9229            assert_eq!(
 9230                view.selections.display_ranges(cx),
 9231                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9232            );
 9233        });
 9234
 9235        view.update(cx, |view, cx| {
 9236            view.change_selections(None, cx, |s| {
 9237                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 9238            });
 9239            view.add_selection_below(&AddSelectionBelow, cx);
 9240            assert_eq!(
 9241                view.selections.display_ranges(cx),
 9242                vec![
 9243                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9244                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9245                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9246                ]
 9247            );
 9248        });
 9249
 9250        view.update(cx, |view, cx| {
 9251            view.add_selection_below(&AddSelectionBelow, cx);
 9252            assert_eq!(
 9253                view.selections.display_ranges(cx),
 9254                vec![
 9255                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9256                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9257                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9258                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 9259                ]
 9260            );
 9261        });
 9262
 9263        view.update(cx, |view, cx| {
 9264            view.add_selection_above(&AddSelectionAbove, cx);
 9265            assert_eq!(
 9266                view.selections.display_ranges(cx),
 9267                vec![
 9268                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9269                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9270                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9271                ]
 9272            );
 9273        });
 9274
 9275        view.update(cx, |view, cx| {
 9276            view.change_selections(None, cx, |s| {
 9277                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 9278            });
 9279        });
 9280        view.update(cx, |view, cx| {
 9281            view.add_selection_above(&AddSelectionAbove, cx);
 9282            assert_eq!(
 9283                view.selections.display_ranges(cx),
 9284                vec![
 9285                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 9286                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9287                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9288                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9289                ]
 9290            );
 9291        });
 9292
 9293        view.update(cx, |view, cx| {
 9294            view.add_selection_below(&AddSelectionBelow, cx);
 9295            assert_eq!(
 9296                view.selections.display_ranges(cx),
 9297                vec![
 9298                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9299                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9300                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9301                ]
 9302            );
 9303        });
 9304    }
 9305
 9306    #[gpui::test]
 9307    async fn test_select_next(cx: &mut gpui::TestAppContext) {
 9308        let mut cx = EditorTestContext::new(cx);
 9309        cx.set_state("abc\nˇabc abc\ndefabc\nabc");
 9310
 9311        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9312        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9313
 9314        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9315        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9316
 9317        cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx));
 9318        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9319
 9320        cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx));
 9321        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9322
 9323        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9324        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9325
 9326        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9327        cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9328    }
 9329
 9330    #[gpui::test]
 9331    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 9332        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9333        let language = Arc::new(Language::new(
 9334            LanguageConfig::default(),
 9335            Some(tree_sitter_rust::language()),
 9336        ));
 9337
 9338        let text = r#"
 9339            use mod1::mod2::{mod3, mod4};
 9340
 9341            fn fn_1(param1: bool, param2: &str) {
 9342                let var1 = "text";
 9343            }
 9344        "#
 9345        .unindent();
 9346
 9347        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9348        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9349        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9350        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9351            .await;
 9352
 9353        view.update(cx, |view, cx| {
 9354            view.change_selections(None, cx, |s| {
 9355                s.select_display_ranges([
 9356                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9357                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9358                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9359                ]);
 9360            });
 9361            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9362        });
 9363        assert_eq!(
 9364            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 9365            &[
 9366                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9367                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9368                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9369            ]
 9370        );
 9371
 9372        view.update(cx, |view, cx| {
 9373            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9374        });
 9375        assert_eq!(
 9376            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9377            &[
 9378                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9379                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9380            ]
 9381        );
 9382
 9383        view.update(cx, |view, cx| {
 9384            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9385        });
 9386        assert_eq!(
 9387            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9388            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9389        );
 9390
 9391        // Trying to expand the selected syntax node one more time has no effect.
 9392        view.update(cx, |view, cx| {
 9393            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9394        });
 9395        assert_eq!(
 9396            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9397            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9398        );
 9399
 9400        view.update(cx, |view, cx| {
 9401            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9402        });
 9403        assert_eq!(
 9404            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9405            &[
 9406                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9407                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9408            ]
 9409        );
 9410
 9411        view.update(cx, |view, cx| {
 9412            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9413        });
 9414        assert_eq!(
 9415            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9416            &[
 9417                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9418                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9419                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9420            ]
 9421        );
 9422
 9423        view.update(cx, |view, cx| {
 9424            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9425        });
 9426        assert_eq!(
 9427            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9428            &[
 9429                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9430                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9431                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9432            ]
 9433        );
 9434
 9435        // Trying to shrink the selected syntax node one more time has no effect.
 9436        view.update(cx, |view, cx| {
 9437            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9438        });
 9439        assert_eq!(
 9440            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9441            &[
 9442                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9443                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9444                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9445            ]
 9446        );
 9447
 9448        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9449        // a fold.
 9450        view.update(cx, |view, cx| {
 9451            view.fold_ranges(
 9452                vec![
 9453                    Point::new(0, 21)..Point::new(0, 24),
 9454                    Point::new(3, 20)..Point::new(3, 22),
 9455                ],
 9456                cx,
 9457            );
 9458            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9459        });
 9460        assert_eq!(
 9461            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9462            &[
 9463                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9464                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9465                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9466            ]
 9467        );
 9468    }
 9469
 9470    #[gpui::test]
 9471    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9472        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9473        let language = Arc::new(
 9474            Language::new(
 9475                LanguageConfig {
 9476                    brackets: vec![
 9477                        BracketPair {
 9478                            start: "{".to_string(),
 9479                            end: "}".to_string(),
 9480                            close: false,
 9481                            newline: true,
 9482                        },
 9483                        BracketPair {
 9484                            start: "(".to_string(),
 9485                            end: ")".to_string(),
 9486                            close: false,
 9487                            newline: true,
 9488                        },
 9489                    ],
 9490                    ..Default::default()
 9491                },
 9492                Some(tree_sitter_rust::language()),
 9493            )
 9494            .with_indents_query(
 9495                r#"
 9496                (_ "(" ")" @end) @indent
 9497                (_ "{" "}" @end) @indent
 9498                "#,
 9499            )
 9500            .unwrap(),
 9501        );
 9502
 9503        let text = "fn a() {}";
 9504
 9505        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9506        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9507        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9508        editor
 9509            .condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9510            .await;
 9511
 9512        editor.update(cx, |editor, cx| {
 9513            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 9514            editor.newline(&Newline, cx);
 9515            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9516            assert_eq!(
 9517                editor.selections.ranges(cx),
 9518                &[
 9519                    Point::new(1, 4)..Point::new(1, 4),
 9520                    Point::new(3, 4)..Point::new(3, 4),
 9521                    Point::new(5, 0)..Point::new(5, 0)
 9522                ]
 9523            );
 9524        });
 9525    }
 9526
 9527    #[gpui::test]
 9528    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9529        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9530        let language = Arc::new(Language::new(
 9531            LanguageConfig {
 9532                brackets: vec![
 9533                    BracketPair {
 9534                        start: "{".to_string(),
 9535                        end: "}".to_string(),
 9536                        close: true,
 9537                        newline: true,
 9538                    },
 9539                    BracketPair {
 9540                        start: "/*".to_string(),
 9541                        end: " */".to_string(),
 9542                        close: true,
 9543                        newline: true,
 9544                    },
 9545                    BracketPair {
 9546                        start: "[".to_string(),
 9547                        end: "]".to_string(),
 9548                        close: false,
 9549                        newline: true,
 9550                    },
 9551                ],
 9552                autoclose_before: "})]".to_string(),
 9553                ..Default::default()
 9554            },
 9555            Some(tree_sitter_rust::language()),
 9556        ));
 9557
 9558        let text = r#"
 9559            a
 9560
 9561            /
 9562
 9563        "#
 9564        .unindent();
 9565
 9566        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9567        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9568        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9569        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9570            .await;
 9571
 9572        view.update(cx, |view, cx| {
 9573            view.change_selections(None, cx, |s| {
 9574                s.select_display_ranges([
 9575                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9576                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9577                ])
 9578            });
 9579
 9580            view.handle_input("{", cx);
 9581            view.handle_input("{", cx);
 9582            view.handle_input("{", cx);
 9583            assert_eq!(
 9584                view.text(cx),
 9585                "
 9586                {{{}}}
 9587                {{{}}}
 9588                /
 9589
 9590                "
 9591                .unindent()
 9592            );
 9593
 9594            view.move_right(&MoveRight, cx);
 9595            view.handle_input("}", cx);
 9596            view.handle_input("}", cx);
 9597            view.handle_input("}", cx);
 9598            assert_eq!(
 9599                view.text(cx),
 9600                "
 9601                {{{}}}}
 9602                {{{}}}}
 9603                /
 9604
 9605                "
 9606                .unindent()
 9607            );
 9608
 9609            view.undo(&Undo, cx);
 9610            view.handle_input("/", cx);
 9611            view.handle_input("*", cx);
 9612            assert_eq!(
 9613                view.text(cx),
 9614                "
 9615                /* */
 9616                /* */
 9617                /
 9618
 9619                "
 9620                .unindent()
 9621            );
 9622
 9623            view.undo(&Undo, cx);
 9624            view.change_selections(None, cx, |s| {
 9625                s.select_display_ranges([
 9626                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9627                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9628                ])
 9629            });
 9630            view.handle_input("*", cx);
 9631            assert_eq!(
 9632                view.text(cx),
 9633                "
 9634                a
 9635
 9636                /*
 9637                *
 9638                "
 9639                .unindent()
 9640            );
 9641
 9642            // Don't autoclose if the next character isn't whitespace and isn't
 9643            // listed in the language's "autoclose_before" section.
 9644            view.finalize_last_transaction(cx);
 9645            view.change_selections(None, cx, |s| {
 9646                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 9647            });
 9648            view.handle_input("{", cx);
 9649            assert_eq!(
 9650                view.text(cx),
 9651                "
 9652                {a
 9653
 9654                /*
 9655                *
 9656                "
 9657                .unindent()
 9658            );
 9659
 9660            view.undo(&Undo, cx);
 9661            view.change_selections(None, cx, |s| {
 9662                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 9663            });
 9664            view.handle_input("{", cx);
 9665            assert_eq!(
 9666                view.text(cx),
 9667                "
 9668                {a}
 9669
 9670                /*
 9671                *
 9672                "
 9673                .unindent()
 9674            );
 9675            assert_eq!(
 9676                view.selections.display_ranges(cx),
 9677                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9678            );
 9679
 9680            view.undo(&Undo, cx);
 9681            view.handle_input("[", cx);
 9682            assert_eq!(
 9683                view.text(cx),
 9684                "
 9685                [a]
 9686                
 9687                /*
 9688                *
 9689                "
 9690                .unindent()
 9691            );
 9692            assert_eq!(
 9693                view.selections.display_ranges(cx),
 9694                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9695            );
 9696
 9697            view.undo(&Undo, cx);
 9698            view.change_selections(None, cx, |s| {
 9699                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9700            });
 9701            view.handle_input("[", cx);
 9702            assert_eq!(
 9703                view.text(cx),
 9704                "
 9705                a[
 9706                
 9707                /*
 9708                *
 9709                "
 9710                .unindent()
 9711            );
 9712            assert_eq!(
 9713                view.selections.display_ranges(cx),
 9714                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9715            );
 9716        });
 9717    }
 9718
 9719    #[gpui::test]
 9720    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9721        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9722        let language = Arc::new(Language::new(
 9723            LanguageConfig {
 9724                brackets: vec![BracketPair {
 9725                    start: "{".to_string(),
 9726                    end: "}".to_string(),
 9727                    close: true,
 9728                    newline: true,
 9729                }],
 9730                ..Default::default()
 9731            },
 9732            Some(tree_sitter_rust::language()),
 9733        ));
 9734
 9735        let text = r#"
 9736            a
 9737            b
 9738            c
 9739        "#
 9740        .unindent();
 9741
 9742        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9743        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9744        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9745        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9746            .await;
 9747
 9748        view.update(cx, |view, cx| {
 9749            view.change_selections(None, cx, |s| {
 9750                s.select_display_ranges([
 9751                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9752                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9753                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9754                ])
 9755            });
 9756
 9757            view.handle_input("{", cx);
 9758            view.handle_input("{", cx);
 9759            view.handle_input("{", cx);
 9760            assert_eq!(
 9761                view.text(cx),
 9762                "
 9763                {{{a}}}
 9764                {{{b}}}
 9765                {{{c}}}
 9766                "
 9767                .unindent()
 9768            );
 9769            assert_eq!(
 9770                view.selections.display_ranges(cx),
 9771                [
 9772                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9773                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9774                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9775                ]
 9776            );
 9777
 9778            view.undo(&Undo, cx);
 9779            assert_eq!(
 9780                view.text(cx),
 9781                "
 9782                a
 9783                b
 9784                c
 9785                "
 9786                .unindent()
 9787            );
 9788            assert_eq!(
 9789                view.selections.display_ranges(cx),
 9790                [
 9791                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9792                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9793                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9794                ]
 9795            );
 9796        });
 9797    }
 9798
 9799    #[gpui::test]
 9800    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9801        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9802        let language = Arc::new(Language::new(
 9803            LanguageConfig {
 9804                brackets: vec![BracketPair {
 9805                    start: "{".to_string(),
 9806                    end: "}".to_string(),
 9807                    close: true,
 9808                    newline: true,
 9809                }],
 9810                autoclose_before: "}".to_string(),
 9811                ..Default::default()
 9812            },
 9813            Some(tree_sitter_rust::language()),
 9814        ));
 9815
 9816        let text = r#"
 9817            a
 9818            b
 9819            c
 9820        "#
 9821        .unindent();
 9822
 9823        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9824        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9825        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9826        editor
 9827            .condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9828            .await;
 9829
 9830        editor.update(cx, |editor, cx| {
 9831            editor.change_selections(None, cx, |s| {
 9832                s.select_ranges([
 9833                    Point::new(0, 1)..Point::new(0, 1),
 9834                    Point::new(1, 1)..Point::new(1, 1),
 9835                    Point::new(2, 1)..Point::new(2, 1),
 9836                ])
 9837            });
 9838
 9839            editor.handle_input("{", cx);
 9840            editor.handle_input("{", cx);
 9841            editor.handle_input("_", cx);
 9842            assert_eq!(
 9843                editor.text(cx),
 9844                "
 9845                a{{_}}
 9846                b{{_}}
 9847                c{{_}}
 9848                "
 9849                .unindent()
 9850            );
 9851            assert_eq!(
 9852                editor.selections.ranges::<Point>(cx),
 9853                [
 9854                    Point::new(0, 4)..Point::new(0, 4),
 9855                    Point::new(1, 4)..Point::new(1, 4),
 9856                    Point::new(2, 4)..Point::new(2, 4)
 9857                ]
 9858            );
 9859
 9860            editor.backspace(&Default::default(), cx);
 9861            editor.backspace(&Default::default(), cx);
 9862            assert_eq!(
 9863                editor.text(cx),
 9864                "
 9865                a{}
 9866                b{}
 9867                c{}
 9868                "
 9869                .unindent()
 9870            );
 9871            assert_eq!(
 9872                editor.selections.ranges::<Point>(cx),
 9873                [
 9874                    Point::new(0, 2)..Point::new(0, 2),
 9875                    Point::new(1, 2)..Point::new(1, 2),
 9876                    Point::new(2, 2)..Point::new(2, 2)
 9877                ]
 9878            );
 9879
 9880            editor.delete_to_previous_word_start(&Default::default(), cx);
 9881            assert_eq!(
 9882                editor.text(cx),
 9883                "
 9884                a
 9885                b
 9886                c
 9887                "
 9888                .unindent()
 9889            );
 9890            assert_eq!(
 9891                editor.selections.ranges::<Point>(cx),
 9892                [
 9893                    Point::new(0, 1)..Point::new(0, 1),
 9894                    Point::new(1, 1)..Point::new(1, 1),
 9895                    Point::new(2, 1)..Point::new(2, 1)
 9896                ]
 9897            );
 9898        });
 9899    }
 9900
 9901    #[gpui::test]
 9902    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9903        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9904
 9905        let (text, insertion_ranges) = marked_text_ranges(
 9906            indoc! {"
 9907                a.ˇ b
 9908                a.ˇ b
 9909                a.ˇ b
 9910            "},
 9911            false,
 9912        );
 9913
 9914        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9915        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9916
 9917        editor.update(cx, |editor, cx| {
 9918            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9919
 9920            editor
 9921                .insert_snippet(&insertion_ranges, snippet, cx)
 9922                .unwrap();
 9923
 9924            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text: &str) {
 9925                let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
 9926                assert_eq!(editor.text(cx), expected_text);
 9927                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9928            }
 9929
 9930            assert(
 9931                editor,
 9932                cx,
 9933                indoc! {"
 9934                    a.f(«one», two, «three») b
 9935                    a.f(«one», two, «three») b
 9936                    a.f(«one», two, «three») b
 9937                "},
 9938            );
 9939
 9940            // Can't move earlier than the first tab stop
 9941            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9942            assert(
 9943                editor,
 9944                cx,
 9945                indoc! {"
 9946                    a.f(«one», two, «three») b
 9947                    a.f(«one», two, «three») b
 9948                    a.f(«one», two, «three») b
 9949                "},
 9950            );
 9951
 9952            assert!(editor.move_to_next_snippet_tabstop(cx));
 9953            assert(
 9954                editor,
 9955                cx,
 9956                indoc! {"
 9957                    a.f(one, «two», three) b
 9958                    a.f(one, «two», three) b
 9959                    a.f(one, «two», three) b
 9960                "},
 9961            );
 9962
 9963            editor.move_to_prev_snippet_tabstop(cx);
 9964            assert(
 9965                editor,
 9966                cx,
 9967                indoc! {"
 9968                    a.f(«one», two, «three») b
 9969                    a.f(«one», two, «three») b
 9970                    a.f(«one», two, «three») b
 9971                "},
 9972            );
 9973
 9974            assert!(editor.move_to_next_snippet_tabstop(cx));
 9975            assert(
 9976                editor,
 9977                cx,
 9978                indoc! {"
 9979                    a.f(one, «two», three) b
 9980                    a.f(one, «two», three) b
 9981                    a.f(one, «two», three) b
 9982                "},
 9983            );
 9984            assert!(editor.move_to_next_snippet_tabstop(cx));
 9985            assert(
 9986                editor,
 9987                cx,
 9988                indoc! {"
 9989                    a.f(one, two, three)ˇ b
 9990                    a.f(one, two, three)ˇ b
 9991                    a.f(one, two, three)ˇ b
 9992                "},
 9993            );
 9994
 9995            // As soon as the last tab stop is reached, snippet state is gone
 9996            editor.move_to_prev_snippet_tabstop(cx);
 9997            assert(
 9998                editor,
 9999                cx,
10000                indoc! {"
10001                    a.f(one, two, three)ˇ b
10002                    a.f(one, two, three)ˇ b
10003                    a.f(one, two, three)ˇ b
10004                "},
10005            );
10006        });
10007    }
10008
10009    #[gpui::test]
10010    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
10011        cx.foreground().forbid_parking();
10012
10013        let mut language = Language::new(
10014            LanguageConfig {
10015                name: "Rust".into(),
10016                path_suffixes: vec!["rs".to_string()],
10017                ..Default::default()
10018            },
10019            Some(tree_sitter_rust::language()),
10020        );
10021        let mut fake_servers = language
10022            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10023                capabilities: lsp::ServerCapabilities {
10024                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
10025                    ..Default::default()
10026                },
10027                ..Default::default()
10028            }))
10029            .await;
10030
10031        let fs = FakeFs::new(cx.background());
10032        fs.insert_file("/file.rs", Default::default()).await;
10033
10034        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10035        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10036        let buffer = project
10037            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10038            .await
10039            .unwrap();
10040
10041        cx.foreground().start_waiting();
10042        let fake_server = fake_servers.next().await.unwrap();
10043
10044        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10045        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10046        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10047        assert!(cx.read(|cx| editor.is_dirty(cx)));
10048
10049        let save = cx.update(|cx| editor.save(project.clone(), cx));
10050        fake_server
10051            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10052                assert_eq!(
10053                    params.text_document.uri,
10054                    lsp::Url::from_file_path("/file.rs").unwrap()
10055                );
10056                assert_eq!(params.options.tab_size, 4);
10057                Ok(Some(vec![lsp::TextEdit::new(
10058                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10059                    ", ".to_string(),
10060                )]))
10061            })
10062            .next()
10063            .await;
10064        cx.foreground().start_waiting();
10065        save.await.unwrap();
10066        assert_eq!(
10067            editor.read_with(cx, |editor, cx| editor.text(cx)),
10068            "one, two\nthree\n"
10069        );
10070        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10071
10072        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10073        assert!(cx.read(|cx| editor.is_dirty(cx)));
10074
10075        // Ensure we can still save even if formatting hangs.
10076        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10077            assert_eq!(
10078                params.text_document.uri,
10079                lsp::Url::from_file_path("/file.rs").unwrap()
10080            );
10081            futures::future::pending::<()>().await;
10082            unreachable!()
10083        });
10084        let save = cx.update(|cx| editor.save(project.clone(), cx));
10085        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10086        cx.foreground().start_waiting();
10087        save.await.unwrap();
10088        assert_eq!(
10089            editor.read_with(cx, |editor, cx| editor.text(cx)),
10090            "one\ntwo\nthree\n"
10091        );
10092        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10093
10094        // Set rust language override and assert overriden tabsize is sent to language server
10095        cx.update(|cx| {
10096            cx.update_global::<Settings, _, _>(|settings, _| {
10097                settings.language_overrides.insert(
10098                    "Rust".into(),
10099                    EditorSettings {
10100                        tab_size: Some(8.try_into().unwrap()),
10101                        ..Default::default()
10102                    },
10103                );
10104            })
10105        });
10106
10107        let save = cx.update(|cx| editor.save(project.clone(), cx));
10108        fake_server
10109            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10110                assert_eq!(
10111                    params.text_document.uri,
10112                    lsp::Url::from_file_path("/file.rs").unwrap()
10113                );
10114                assert_eq!(params.options.tab_size, 8);
10115                Ok(Some(vec![]))
10116            })
10117            .next()
10118            .await;
10119        cx.foreground().start_waiting();
10120        save.await.unwrap();
10121    }
10122
10123    #[gpui::test]
10124    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
10125        cx.foreground().forbid_parking();
10126
10127        let mut language = Language::new(
10128            LanguageConfig {
10129                name: "Rust".into(),
10130                path_suffixes: vec!["rs".to_string()],
10131                ..Default::default()
10132            },
10133            Some(tree_sitter_rust::language()),
10134        );
10135        let mut fake_servers = language
10136            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10137                capabilities: lsp::ServerCapabilities {
10138                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
10139                    ..Default::default()
10140                },
10141                ..Default::default()
10142            }))
10143            .await;
10144
10145        let fs = FakeFs::new(cx.background());
10146        fs.insert_file("/file.rs", Default::default()).await;
10147
10148        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10149        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10150        let buffer = project
10151            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10152            .await
10153            .unwrap();
10154
10155        cx.foreground().start_waiting();
10156        let fake_server = fake_servers.next().await.unwrap();
10157
10158        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10159        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10160        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10161        assert!(cx.read(|cx| editor.is_dirty(cx)));
10162
10163        let save = cx.update(|cx| editor.save(project.clone(), cx));
10164        fake_server
10165            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10166                assert_eq!(
10167                    params.text_document.uri,
10168                    lsp::Url::from_file_path("/file.rs").unwrap()
10169                );
10170                assert_eq!(params.options.tab_size, 4);
10171                Ok(Some(vec![lsp::TextEdit::new(
10172                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10173                    ", ".to_string(),
10174                )]))
10175            })
10176            .next()
10177            .await;
10178        cx.foreground().start_waiting();
10179        save.await.unwrap();
10180        assert_eq!(
10181            editor.read_with(cx, |editor, cx| editor.text(cx)),
10182            "one, two\nthree\n"
10183        );
10184        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10185
10186        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10187        assert!(cx.read(|cx| editor.is_dirty(cx)));
10188
10189        // Ensure we can still save even if formatting hangs.
10190        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
10191            move |params, _| async move {
10192                assert_eq!(
10193                    params.text_document.uri,
10194                    lsp::Url::from_file_path("/file.rs").unwrap()
10195                );
10196                futures::future::pending::<()>().await;
10197                unreachable!()
10198            },
10199        );
10200        let save = cx.update(|cx| editor.save(project.clone(), cx));
10201        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10202        cx.foreground().start_waiting();
10203        save.await.unwrap();
10204        assert_eq!(
10205            editor.read_with(cx, |editor, cx| editor.text(cx)),
10206            "one\ntwo\nthree\n"
10207        );
10208        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10209
10210        // Set rust language override and assert overriden tabsize is sent to language server
10211        cx.update(|cx| {
10212            cx.update_global::<Settings, _, _>(|settings, _| {
10213                settings.language_overrides.insert(
10214                    "Rust".into(),
10215                    EditorSettings {
10216                        tab_size: Some(8.try_into().unwrap()),
10217                        ..Default::default()
10218                    },
10219                );
10220            })
10221        });
10222
10223        let save = cx.update(|cx| editor.save(project.clone(), cx));
10224        fake_server
10225            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10226                assert_eq!(
10227                    params.text_document.uri,
10228                    lsp::Url::from_file_path("/file.rs").unwrap()
10229                );
10230                assert_eq!(params.options.tab_size, 8);
10231                Ok(Some(vec![]))
10232            })
10233            .next()
10234            .await;
10235        cx.foreground().start_waiting();
10236        save.await.unwrap();
10237    }
10238
10239    #[gpui::test]
10240    async fn test_completion(cx: &mut gpui::TestAppContext) {
10241        let mut cx = EditorLspTestContext::new_rust(
10242            lsp::ServerCapabilities {
10243                completion_provider: Some(lsp::CompletionOptions {
10244                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
10245                    ..Default::default()
10246                }),
10247                ..Default::default()
10248            },
10249            cx,
10250        )
10251        .await;
10252
10253        cx.set_state(indoc! {"
10254            oneˇ
10255            two
10256            three
10257        "});
10258        cx.simulate_keystroke(".");
10259        handle_completion_request(
10260            &mut cx,
10261            indoc! {"
10262                one.|<>
10263                two
10264                three
10265            "},
10266            vec!["first_completion", "second_completion"],
10267        )
10268        .await;
10269        cx.condition(|editor, _| editor.context_menu_visible())
10270            .await;
10271        let apply_additional_edits = cx.update_editor(|editor, cx| {
10272            editor.move_down(&MoveDown, cx);
10273            editor
10274                .confirm_completion(&ConfirmCompletion::default(), cx)
10275                .unwrap()
10276        });
10277        cx.assert_editor_state(indoc! {"
10278            one.second_completionˇ
10279            two
10280            three
10281        "});
10282
10283        handle_resolve_completion_request(
10284            &mut cx,
10285            Some((
10286                indoc! {"
10287                    one.second_completion
10288                    two
10289                    threeˇ
10290                "},
10291                "\nadditional edit",
10292            )),
10293        )
10294        .await;
10295        apply_additional_edits.await.unwrap();
10296        cx.assert_editor_state(indoc! {"
10297            one.second_completionˇ
10298            two
10299            three
10300            additional edit
10301        "});
10302
10303        cx.set_state(indoc! {"
10304            one.second_completion
10305            twoˇ
10306            threeˇ
10307            additional edit
10308        "});
10309        cx.simulate_keystroke(" ");
10310        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10311        cx.simulate_keystroke("s");
10312        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10313
10314        cx.assert_editor_state(indoc! {"
10315            one.second_completion
10316            two sˇ
10317            three sˇ
10318            additional edit
10319        "});
10320        //
10321        handle_completion_request(
10322            &mut cx,
10323            indoc! {"
10324                one.second_completion
10325                two s
10326                three <s|>
10327                additional edit
10328            "},
10329            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10330        )
10331        .await;
10332        cx.condition(|editor, _| editor.context_menu_visible())
10333            .await;
10334
10335        cx.simulate_keystroke("i");
10336
10337        handle_completion_request(
10338            &mut cx,
10339            indoc! {"
10340                one.second_completion
10341                two si
10342                three <si|>
10343                additional edit
10344            "},
10345            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10346        )
10347        .await;
10348        cx.condition(|editor, _| editor.context_menu_visible())
10349            .await;
10350
10351        let apply_additional_edits = cx.update_editor(|editor, cx| {
10352            editor
10353                .confirm_completion(&ConfirmCompletion::default(), cx)
10354                .unwrap()
10355        });
10356        cx.assert_editor_state(indoc! {"
10357            one.second_completion
10358            two sixth_completionˇ
10359            three sixth_completionˇ
10360            additional edit
10361        "});
10362
10363        handle_resolve_completion_request(&mut cx, None).await;
10364        apply_additional_edits.await.unwrap();
10365
10366        cx.update(|cx| {
10367            cx.update_global::<Settings, _, _>(|settings, _| {
10368                settings.show_completions_on_input = false;
10369            })
10370        });
10371        cx.set_state("editorˇ");
10372        cx.simulate_keystroke(".");
10373        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10374        cx.simulate_keystroke("c");
10375        cx.simulate_keystroke("l");
10376        cx.simulate_keystroke("o");
10377        cx.assert_editor_state("editor.cloˇ");
10378        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10379        cx.update_editor(|editor, cx| {
10380            editor.show_completions(&ShowCompletions, cx);
10381        });
10382        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
10383        cx.condition(|editor, _| editor.context_menu_visible())
10384            .await;
10385        let apply_additional_edits = cx.update_editor(|editor, cx| {
10386            editor
10387                .confirm_completion(&ConfirmCompletion::default(), cx)
10388                .unwrap()
10389        });
10390        cx.assert_editor_state("editor.closeˇ");
10391        handle_resolve_completion_request(&mut cx, None).await;
10392        apply_additional_edits.await.unwrap();
10393
10394        // Handle completion request passing a marked string specifying where the completion
10395        // should be triggered from using '|' character, what range should be replaced, and what completions
10396        // should be returned using '<' and '>' to delimit the range
10397        async fn handle_completion_request<'a>(
10398            cx: &mut EditorLspTestContext<'a>,
10399            marked_string: &str,
10400            completions: Vec<&'static str>,
10401        ) {
10402            let complete_from_marker: TextRangeMarker = '|'.into();
10403            let replace_range_marker: TextRangeMarker = ('<', '>').into();
10404            let (_, mut marked_ranges) = marked_text_ranges_by(
10405                marked_string,
10406                vec![complete_from_marker.clone(), replace_range_marker.clone()],
10407            );
10408
10409            let complete_from_position =
10410                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
10411            let replace_range =
10412                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10413
10414            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
10415                let completions = completions.clone();
10416                async move {
10417                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
10418                    assert_eq!(
10419                        params.text_document_position.position,
10420                        complete_from_position
10421                    );
10422                    Ok(Some(lsp::CompletionResponse::Array(
10423                        completions
10424                            .iter()
10425                            .map(|completion_text| lsp::CompletionItem {
10426                                label: completion_text.to_string(),
10427                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
10428                                    range: replace_range,
10429                                    new_text: completion_text.to_string(),
10430                                })),
10431                                ..Default::default()
10432                            })
10433                            .collect(),
10434                    )))
10435                }
10436            })
10437            .next()
10438            .await;
10439        }
10440
10441        async fn handle_resolve_completion_request<'a>(
10442            cx: &mut EditorLspTestContext<'a>,
10443            edit: Option<(&'static str, &'static str)>,
10444        ) {
10445            let edit = edit.map(|(marked_string, new_text)| {
10446                let (_, marked_ranges) = marked_text_ranges(marked_string, false);
10447                let replace_range = cx.to_lsp_range(marked_ranges[0].clone());
10448                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
10449            });
10450
10451            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
10452                let edit = edit.clone();
10453                async move {
10454                    Ok(lsp::CompletionItem {
10455                        additional_text_edits: edit,
10456                        ..Default::default()
10457                    })
10458                }
10459            })
10460            .next()
10461            .await;
10462        }
10463    }
10464
10465    #[gpui::test]
10466    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
10467        cx.update(|cx| cx.set_global(Settings::test(cx)));
10468        let language = Arc::new(Language::new(
10469            LanguageConfig {
10470                line_comment: Some("// ".to_string()),
10471                ..Default::default()
10472            },
10473            Some(tree_sitter_rust::language()),
10474        ));
10475
10476        let text = "
10477            fn a() {
10478                //b();
10479                // c();
10480                //  d();
10481            }
10482        "
10483        .unindent();
10484
10485        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10486        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10487        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10488
10489        view.update(cx, |editor, cx| {
10490            // If multiple selections intersect a line, the line is only
10491            // toggled once.
10492            editor.change_selections(None, cx, |s| {
10493                s.select_display_ranges([
10494                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
10495                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
10496                ])
10497            });
10498            editor.toggle_comments(&ToggleComments, cx);
10499            assert_eq!(
10500                editor.text(cx),
10501                "
10502                    fn a() {
10503                        b();
10504                        c();
10505                         d();
10506                    }
10507                "
10508                .unindent()
10509            );
10510
10511            // The comment prefix is inserted at the same column for every line
10512            // in a selection.
10513            editor.change_selections(None, cx, |s| {
10514                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
10515            });
10516            editor.toggle_comments(&ToggleComments, cx);
10517            assert_eq!(
10518                editor.text(cx),
10519                "
10520                    fn a() {
10521                        // b();
10522                        // c();
10523                        //  d();
10524                    }
10525                "
10526                .unindent()
10527            );
10528
10529            // If a selection ends at the beginning of a line, that line is not toggled.
10530            editor.change_selections(None, cx, |s| {
10531                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
10532            });
10533            editor.toggle_comments(&ToggleComments, cx);
10534            assert_eq!(
10535                editor.text(cx),
10536                "
10537                        fn a() {
10538                            // b();
10539                            c();
10540                            //  d();
10541                        }
10542                    "
10543                .unindent()
10544            );
10545        });
10546    }
10547
10548    #[gpui::test]
10549    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
10550        cx.set_global(Settings::test(cx));
10551        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10552        let multibuffer = cx.add_model(|cx| {
10553            let mut multibuffer = MultiBuffer::new(0);
10554            multibuffer.push_excerpts(
10555                buffer.clone(),
10556                [
10557                    ExcerptRange {
10558                        context: Point::new(0, 0)..Point::new(0, 4),
10559                        primary: None,
10560                    },
10561                    ExcerptRange {
10562                        context: Point::new(1, 0)..Point::new(1, 4),
10563                        primary: None,
10564                    },
10565                ],
10566                cx,
10567            );
10568            multibuffer
10569        });
10570
10571        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
10572
10573        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10574        view.update(cx, |view, cx| {
10575            assert_eq!(view.text(cx), "aaaa\nbbbb");
10576            view.change_selections(None, cx, |s| {
10577                s.select_ranges([
10578                    Point::new(0, 0)..Point::new(0, 0),
10579                    Point::new(1, 0)..Point::new(1, 0),
10580                ])
10581            });
10582
10583            view.handle_input("X", cx);
10584            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
10585            assert_eq!(
10586                view.selections.ranges(cx),
10587                [
10588                    Point::new(0, 1)..Point::new(0, 1),
10589                    Point::new(1, 1)..Point::new(1, 1),
10590                ]
10591            )
10592        });
10593    }
10594
10595    #[gpui::test]
10596    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
10597        cx.set_global(Settings::test(cx));
10598        let markers = vec![('[', ']').into(), ('(', ')').into()];
10599        let (initial_text, mut excerpt_ranges) = marked_text_ranges_by(
10600            indoc! {"
10601                [aaaa
10602                (bbbb]
10603                cccc)",
10604            },
10605            markers.clone(),
10606        );
10607        let excerpt_ranges = markers.into_iter().map(|marker| {
10608            let context = excerpt_ranges.remove(&marker).unwrap()[0].clone();
10609            ExcerptRange {
10610                context,
10611                primary: None,
10612            }
10613        });
10614        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
10615        let multibuffer = cx.add_model(|cx| {
10616            let mut multibuffer = MultiBuffer::new(0);
10617            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
10618            multibuffer
10619        });
10620
10621        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10622        view.update(cx, |view, cx| {
10623            let (expected_text, selection_ranges) = marked_text_ranges(
10624                indoc! {"
10625                    aaaa
10626                    bˇbbb
10627                    bˇbbˇb
10628                    cccc"
10629                },
10630                true,
10631            );
10632            assert_eq!(view.text(cx), expected_text);
10633            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
10634
10635            view.handle_input("X", cx);
10636
10637            let (expected_text, expected_selections) = marked_text_ranges(
10638                indoc! {"
10639                    aaaa
10640                    bXˇbbXb
10641                    bXˇbbXˇb
10642                    cccc"
10643                },
10644                false,
10645            );
10646            assert_eq!(view.text(cx), expected_text);
10647            assert_eq!(view.selections.ranges(cx), expected_selections);
10648
10649            view.newline(&Newline, cx);
10650            let (expected_text, expected_selections) = marked_text_ranges(
10651                indoc! {"
10652                    aaaa
10653                    bX
10654                    ˇbbX
10655                    b
10656                    bX
10657                    ˇbbX
10658                    ˇb
10659                    cccc"
10660                },
10661                false,
10662            );
10663            assert_eq!(view.text(cx), expected_text);
10664            assert_eq!(view.selections.ranges(cx), expected_selections);
10665        });
10666    }
10667
10668    #[gpui::test]
10669    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
10670        cx.set_global(Settings::test(cx));
10671        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10672        let mut excerpt1_id = None;
10673        let multibuffer = cx.add_model(|cx| {
10674            let mut multibuffer = MultiBuffer::new(0);
10675            excerpt1_id = multibuffer
10676                .push_excerpts(
10677                    buffer.clone(),
10678                    [
10679                        ExcerptRange {
10680                            context: Point::new(0, 0)..Point::new(1, 4),
10681                            primary: None,
10682                        },
10683                        ExcerptRange {
10684                            context: Point::new(1, 0)..Point::new(2, 4),
10685                            primary: None,
10686                        },
10687                    ],
10688                    cx,
10689                )
10690                .into_iter()
10691                .next();
10692            multibuffer
10693        });
10694        assert_eq!(
10695            multibuffer.read(cx).read(cx).text(),
10696            "aaaa\nbbbb\nbbbb\ncccc"
10697        );
10698        let (_, editor) = cx.add_window(Default::default(), |cx| {
10699            let mut editor = build_editor(multibuffer.clone(), cx);
10700            let snapshot = editor.snapshot(cx);
10701            editor.change_selections(None, cx, |s| {
10702                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
10703            });
10704            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
10705            assert_eq!(
10706                editor.selections.ranges(cx),
10707                [
10708                    Point::new(1, 3)..Point::new(1, 3),
10709                    Point::new(2, 1)..Point::new(2, 1),
10710                ]
10711            );
10712            editor
10713        });
10714
10715        // Refreshing selections is a no-op when excerpts haven't changed.
10716        editor.update(cx, |editor, cx| {
10717            editor.change_selections(None, cx, |s| {
10718                s.refresh();
10719            });
10720            assert_eq!(
10721                editor.selections.ranges(cx),
10722                [
10723                    Point::new(1, 3)..Point::new(1, 3),
10724                    Point::new(2, 1)..Point::new(2, 1),
10725                ]
10726            );
10727        });
10728
10729        multibuffer.update(cx, |multibuffer, cx| {
10730            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10731        });
10732        editor.update(cx, |editor, cx| {
10733            // Removing an excerpt causes the first selection to become degenerate.
10734            assert_eq!(
10735                editor.selections.ranges(cx),
10736                [
10737                    Point::new(0, 0)..Point::new(0, 0),
10738                    Point::new(0, 1)..Point::new(0, 1)
10739                ]
10740            );
10741
10742            // Refreshing selections will relocate the first selection to the original buffer
10743            // location.
10744            editor.change_selections(None, cx, |s| {
10745                s.refresh();
10746            });
10747            assert_eq!(
10748                editor.selections.ranges(cx),
10749                [
10750                    Point::new(0, 1)..Point::new(0, 1),
10751                    Point::new(0, 3)..Point::new(0, 3)
10752                ]
10753            );
10754            assert!(editor.selections.pending_anchor().is_some());
10755        });
10756    }
10757
10758    #[gpui::test]
10759    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10760        cx.set_global(Settings::test(cx));
10761        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10762        let mut excerpt1_id = None;
10763        let multibuffer = cx.add_model(|cx| {
10764            let mut multibuffer = MultiBuffer::new(0);
10765            excerpt1_id = multibuffer
10766                .push_excerpts(
10767                    buffer.clone(),
10768                    [
10769                        ExcerptRange {
10770                            context: Point::new(0, 0)..Point::new(1, 4),
10771                            primary: None,
10772                        },
10773                        ExcerptRange {
10774                            context: Point::new(1, 0)..Point::new(2, 4),
10775                            primary: None,
10776                        },
10777                    ],
10778                    cx,
10779                )
10780                .into_iter()
10781                .next();
10782            multibuffer
10783        });
10784        assert_eq!(
10785            multibuffer.read(cx).read(cx).text(),
10786            "aaaa\nbbbb\nbbbb\ncccc"
10787        );
10788        let (_, editor) = cx.add_window(Default::default(), |cx| {
10789            let mut editor = build_editor(multibuffer.clone(), cx);
10790            let snapshot = editor.snapshot(cx);
10791            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10792            assert_eq!(
10793                editor.selections.ranges(cx),
10794                [Point::new(1, 3)..Point::new(1, 3)]
10795            );
10796            editor
10797        });
10798
10799        multibuffer.update(cx, |multibuffer, cx| {
10800            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10801        });
10802        editor.update(cx, |editor, cx| {
10803            assert_eq!(
10804                editor.selections.ranges(cx),
10805                [Point::new(0, 0)..Point::new(0, 0)]
10806            );
10807
10808            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10809            editor.change_selections(None, cx, |s| {
10810                s.refresh();
10811            });
10812            assert_eq!(
10813                editor.selections.ranges(cx),
10814                [Point::new(0, 3)..Point::new(0, 3)]
10815            );
10816            assert!(editor.selections.pending_anchor().is_some());
10817        });
10818    }
10819
10820    #[gpui::test]
10821    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10822        cx.update(|cx| cx.set_global(Settings::test(cx)));
10823        let language = Arc::new(
10824            Language::new(
10825                LanguageConfig {
10826                    brackets: vec![
10827                        BracketPair {
10828                            start: "{".to_string(),
10829                            end: "}".to_string(),
10830                            close: true,
10831                            newline: true,
10832                        },
10833                        BracketPair {
10834                            start: "/* ".to_string(),
10835                            end: " */".to_string(),
10836                            close: true,
10837                            newline: true,
10838                        },
10839                    ],
10840                    ..Default::default()
10841                },
10842                Some(tree_sitter_rust::language()),
10843            )
10844            .with_indents_query("")
10845            .unwrap(),
10846        );
10847
10848        let text = concat!(
10849            "{   }\n",     // Suppress rustfmt
10850            "  x\n",       //
10851            "  /*   */\n", //
10852            "x\n",         //
10853            "{{} }\n",     //
10854        );
10855
10856        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10857        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10858        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10859        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10860            .await;
10861
10862        view.update(cx, |view, cx| {
10863            view.change_selections(None, cx, |s| {
10864                s.select_display_ranges([
10865                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10866                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10867                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10868                ])
10869            });
10870            view.newline(&Newline, cx);
10871
10872            assert_eq!(
10873                view.buffer().read(cx).read(cx).text(),
10874                concat!(
10875                    "{ \n",    // Suppress rustfmt
10876                    "\n",      //
10877                    "}\n",     //
10878                    "  x\n",   //
10879                    "  /* \n", //
10880                    "  \n",    //
10881                    "  */\n",  //
10882                    "x\n",     //
10883                    "{{} \n",  //
10884                    "}\n",     //
10885                )
10886            );
10887        });
10888    }
10889
10890    #[gpui::test]
10891    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10892        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10893
10894        cx.set_global(Settings::test(cx));
10895        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10896
10897        editor.update(cx, |editor, cx| {
10898            struct Type1;
10899            struct Type2;
10900
10901            let buffer = buffer.read(cx).snapshot(cx);
10902
10903            let anchor_range = |range: Range<Point>| {
10904                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10905            };
10906
10907            editor.highlight_background::<Type1>(
10908                vec![
10909                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10910                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10911                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10912                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10913                ],
10914                |_| Color::red(),
10915                cx,
10916            );
10917            editor.highlight_background::<Type2>(
10918                vec![
10919                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10920                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10921                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10922                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10923                ],
10924                |_| Color::green(),
10925                cx,
10926            );
10927
10928            let snapshot = editor.snapshot(cx);
10929            let mut highlighted_ranges = editor.background_highlights_in_range(
10930                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10931                &snapshot,
10932                cx.global::<Settings>().theme.as_ref(),
10933            );
10934            // Enforce a consistent ordering based on color without relying on the ordering of the
10935            // highlight's `TypeId` which is non-deterministic.
10936            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10937            assert_eq!(
10938                highlighted_ranges,
10939                &[
10940                    (
10941                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10942                        Color::green(),
10943                    ),
10944                    (
10945                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10946                        Color::green(),
10947                    ),
10948                    (
10949                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10950                        Color::red(),
10951                    ),
10952                    (
10953                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10954                        Color::red(),
10955                    ),
10956                ]
10957            );
10958            assert_eq!(
10959                editor.background_highlights_in_range(
10960                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10961                    &snapshot,
10962                    cx.global::<Settings>().theme.as_ref(),
10963                ),
10964                &[(
10965                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10966                    Color::red(),
10967                )]
10968            );
10969        });
10970    }
10971
10972    #[gpui::test]
10973    fn test_following(cx: &mut gpui::MutableAppContext) {
10974        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10975
10976        cx.set_global(Settings::test(cx));
10977
10978        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10979        let (_, follower) = cx.add_window(
10980            WindowOptions {
10981                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10982                ..Default::default()
10983            },
10984            |cx| build_editor(buffer.clone(), cx),
10985        );
10986
10987        let pending_update = Rc::new(RefCell::new(None));
10988        follower.update(cx, {
10989            let update = pending_update.clone();
10990            |_, cx| {
10991                cx.subscribe(&leader, move |_, leader, event, cx| {
10992                    leader
10993                        .read(cx)
10994                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10995                })
10996                .detach();
10997            }
10998        });
10999
11000        // Update the selections only
11001        leader.update(cx, |leader, cx| {
11002            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
11003        });
11004        follower.update(cx, |follower, cx| {
11005            follower
11006                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11007                .unwrap();
11008        });
11009        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
11010
11011        // Update the scroll position only
11012        leader.update(cx, |leader, cx| {
11013            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
11014        });
11015        follower.update(cx, |follower, cx| {
11016            follower
11017                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11018                .unwrap();
11019        });
11020        assert_eq!(
11021            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
11022            vec2f(1.5, 3.5)
11023        );
11024
11025        // Update the selections and scroll position
11026        leader.update(cx, |leader, cx| {
11027            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
11028            leader.request_autoscroll(Autoscroll::Newest, cx);
11029            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
11030        });
11031        follower.update(cx, |follower, cx| {
11032            let initial_scroll_position = follower.scroll_position(cx);
11033            follower
11034                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11035                .unwrap();
11036            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
11037            assert!(follower.autoscroll_request.is_some());
11038        });
11039        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
11040
11041        // Creating a pending selection that precedes another selection
11042        leader.update(cx, |leader, cx| {
11043            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
11044            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
11045        });
11046        follower.update(cx, |follower, cx| {
11047            follower
11048                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11049                .unwrap();
11050        });
11051        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
11052
11053        // Extend the pending selection so that it surrounds another selection
11054        leader.update(cx, |leader, cx| {
11055            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
11056        });
11057        follower.update(cx, |follower, cx| {
11058            follower
11059                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11060                .unwrap();
11061        });
11062        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
11063    }
11064
11065    #[test]
11066    fn test_combine_syntax_and_fuzzy_match_highlights() {
11067        let string = "abcdefghijklmnop";
11068        let syntax_ranges = [
11069            (
11070                0..3,
11071                HighlightStyle {
11072                    color: Some(Color::red()),
11073                    ..Default::default()
11074                },
11075            ),
11076            (
11077                4..8,
11078                HighlightStyle {
11079                    color: Some(Color::green()),
11080                    ..Default::default()
11081                },
11082            ),
11083        ];
11084        let match_indices = [4, 6, 7, 8];
11085        assert_eq!(
11086            combine_syntax_and_fuzzy_match_highlights(
11087                string,
11088                Default::default(),
11089                syntax_ranges.into_iter(),
11090                &match_indices,
11091            ),
11092            &[
11093                (
11094                    0..3,
11095                    HighlightStyle {
11096                        color: Some(Color::red()),
11097                        ..Default::default()
11098                    },
11099                ),
11100                (
11101                    4..5,
11102                    HighlightStyle {
11103                        color: Some(Color::green()),
11104                        weight: Some(fonts::Weight::BOLD),
11105                        ..Default::default()
11106                    },
11107                ),
11108                (
11109                    5..6,
11110                    HighlightStyle {
11111                        color: Some(Color::green()),
11112                        ..Default::default()
11113                    },
11114                ),
11115                (
11116                    6..8,
11117                    HighlightStyle {
11118                        color: Some(Color::green()),
11119                        weight: Some(fonts::Weight::BOLD),
11120                        ..Default::default()
11121                    },
11122                ),
11123                (
11124                    8..9,
11125                    HighlightStyle {
11126                        weight: Some(fonts::Weight::BOLD),
11127                        ..Default::default()
11128                    },
11129                ),
11130            ]
11131        );
11132    }
11133
11134    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
11135        let point = DisplayPoint::new(row as u32, column as u32);
11136        point..point
11137    }
11138
11139    fn assert_selection_ranges(marked_text: &str, view: &mut Editor, cx: &mut ViewContext<Editor>) {
11140        let (text, ranges) = marked_text_ranges(marked_text, true);
11141        assert_eq!(view.text(cx), text);
11142        assert_eq!(
11143            view.selections.ranges(cx),
11144            ranges,
11145            "Assert selections are {}",
11146            marked_text
11147        );
11148    }
11149}
11150
11151trait RangeExt<T> {
11152    fn sorted(&self) -> Range<T>;
11153    fn to_inclusive(&self) -> RangeInclusive<T>;
11154}
11155
11156impl<T: Ord + Clone> RangeExt<T> for Range<T> {
11157    fn sorted(&self) -> Self {
11158        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
11159    }
11160
11161    fn to_inclusive(&self) -> RangeInclusive<T> {
11162        self.start.clone()..=self.end.clone()
11163    }
11164}
11165
11166trait RangeToAnchorExt {
11167    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
11168}
11169
11170impl<T: ToOffset> RangeToAnchorExt for Range<T> {
11171    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
11172        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
11173    }
11174}