editor.rs

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