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