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