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