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                    primary: None,
 7725                }],
 7726                cx,
 7727            );
 7728            multibuffer.push_excerpts(
 7729                rust_buffer.clone(),
 7730                [ExcerptRange {
 7731                    context: Point::new(0, 0)..Point::new(1, 0),
 7732                    primary: None,
 7733                }],
 7734                cx,
 7735            );
 7736            multibuffer
 7737        });
 7738
 7739        cx.add_window(Default::default(), |cx| {
 7740            let mut editor = build_editor(multibuffer, cx);
 7741
 7742            assert_eq!(
 7743                editor.text(cx),
 7744                indoc! {"
 7745                    a = 1
 7746                    b = 2
 7747
 7748                    const c: usize = 3;
 7749                "}
 7750            );
 7751
 7752            select_ranges(
 7753                &mut editor,
 7754                indoc! {"
 7755                    [a] = 1
 7756                    b = 2
 7757
 7758                    [const c:] usize = 3;
 7759                "},
 7760                cx,
 7761            );
 7762
 7763            editor.tab(&Tab, cx);
 7764            assert_text_with_selections(
 7765                &mut editor,
 7766                indoc! {"
 7767                      [a] = 1
 7768                    b = 2
 7769
 7770                        [const c:] usize = 3;
 7771                "},
 7772                cx,
 7773            );
 7774            editor.tab_prev(&TabPrev, cx);
 7775            assert_text_with_selections(
 7776                &mut editor,
 7777                indoc! {"
 7778                    [a] = 1
 7779                    b = 2
 7780
 7781                    [const c:] usize = 3;
 7782                "},
 7783                cx,
 7784            );
 7785
 7786            editor
 7787        });
 7788    }
 7789
 7790    #[gpui::test]
 7791    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 7792        let mut cx = EditorTestContext::new(cx).await;
 7793        // Basic backspace
 7794        cx.set_state(indoc! {"
 7795            on|e two three
 7796            fou[r} five six
 7797            seven {eight nine
 7798            ]ten"});
 7799        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7800        cx.assert_editor_state(indoc! {"
 7801            o|e two three
 7802            fou| five six
 7803            seven |ten"});
 7804
 7805        // Test backspace inside and around indents
 7806        cx.set_state(indoc! {"
 7807            zero
 7808                |one
 7809                    |two
 7810                | | |  three
 7811            |  |  four"});
 7812        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7813        cx.assert_editor_state(indoc! {"
 7814            zero
 7815            |one
 7816                |two
 7817            |  three|  four"});
 7818
 7819        // Test backspace with line_mode set to true
 7820        cx.update_editor(|e, _| e.selections.line_mode = true);
 7821        cx.set_state(indoc! {"
 7822            The |quick |brown
 7823            fox jumps over
 7824            the lazy dog
 7825            |The qu[ick b}rown"});
 7826        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7827        cx.assert_editor_state(indoc! {"
 7828            |fox jumps over
 7829            the lazy dog|"});
 7830    }
 7831
 7832    #[gpui::test]
 7833    async fn test_delete(cx: &mut gpui::TestAppContext) {
 7834        let mut cx = EditorTestContext::new(cx).await;
 7835
 7836        cx.set_state(indoc! {"
 7837            on|e two three
 7838            fou[r} five six
 7839            seven {eight nine
 7840            ]ten"});
 7841        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 7842        cx.assert_editor_state(indoc! {"
 7843            on| two three
 7844            fou| five six
 7845            seven |ten"});
 7846
 7847        // Test backspace with line_mode set to true
 7848        cx.update_editor(|e, _| e.selections.line_mode = true);
 7849        cx.set_state(indoc! {"
 7850            The |quick |brown
 7851            fox {jum]ps over
 7852            the lazy dog
 7853            |The qu[ick b}rown"});
 7854        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7855        cx.assert_editor_state("|the lazy dog|");
 7856    }
 7857
 7858    #[gpui::test]
 7859    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7860        cx.set_global(Settings::test(cx));
 7861        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7862        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7863        view.update(cx, |view, cx| {
 7864            view.change_selections(None, cx, |s| {
 7865                s.select_display_ranges([
 7866                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7867                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7868                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7869                ])
 7870            });
 7871            view.delete_line(&DeleteLine, cx);
 7872            assert_eq!(view.display_text(cx), "ghi");
 7873            assert_eq!(
 7874                view.selections.display_ranges(cx),
 7875                vec![
 7876                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7877                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7878                ]
 7879            );
 7880        });
 7881
 7882        cx.set_global(Settings::test(cx));
 7883        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7884        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7885        view.update(cx, |view, cx| {
 7886            view.change_selections(None, cx, |s| {
 7887                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 7888            });
 7889            view.delete_line(&DeleteLine, cx);
 7890            assert_eq!(view.display_text(cx), "ghi\n");
 7891            assert_eq!(
 7892                view.selections.display_ranges(cx),
 7893                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 7894            );
 7895        });
 7896    }
 7897
 7898    #[gpui::test]
 7899    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 7900        cx.set_global(Settings::test(cx));
 7901        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7902        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7903        view.update(cx, |view, cx| {
 7904            view.change_selections(None, cx, |s| {
 7905                s.select_display_ranges([
 7906                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 7907                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7908                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7909                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7910                ])
 7911            });
 7912            view.duplicate_line(&DuplicateLine, cx);
 7913            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 7914            assert_eq!(
 7915                view.selections.display_ranges(cx),
 7916                vec![
 7917                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7918                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7919                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7920                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 7921                ]
 7922            );
 7923        });
 7924
 7925        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7926        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7927        view.update(cx, |view, cx| {
 7928            view.change_selections(None, cx, |s| {
 7929                s.select_display_ranges([
 7930                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 7931                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 7932                ])
 7933            });
 7934            view.duplicate_line(&DuplicateLine, cx);
 7935            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 7936            assert_eq!(
 7937                view.selections.display_ranges(cx),
 7938                vec![
 7939                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 7940                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 7941                ]
 7942            );
 7943        });
 7944    }
 7945
 7946    #[gpui::test]
 7947    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 7948        cx.set_global(Settings::test(cx));
 7949        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 7950        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7951        view.update(cx, |view, cx| {
 7952            view.fold_ranges(
 7953                vec![
 7954                    Point::new(0, 2)..Point::new(1, 2),
 7955                    Point::new(2, 3)..Point::new(4, 1),
 7956                    Point::new(7, 0)..Point::new(8, 4),
 7957                ],
 7958                cx,
 7959            );
 7960            view.change_selections(None, cx, |s| {
 7961                s.select_display_ranges([
 7962                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7963                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 7964                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 7965                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 7966                ])
 7967            });
 7968            assert_eq!(
 7969                view.display_text(cx),
 7970                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 7971            );
 7972
 7973            view.move_line_up(&MoveLineUp, cx);
 7974            assert_eq!(
 7975                view.display_text(cx),
 7976                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 7977            );
 7978            assert_eq!(
 7979                view.selections.display_ranges(cx),
 7980                vec![
 7981                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7982                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 7983                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 7984                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 7985                ]
 7986            );
 7987        });
 7988
 7989        view.update(cx, |view, cx| {
 7990            view.move_line_down(&MoveLineDown, cx);
 7991            assert_eq!(
 7992                view.display_text(cx),
 7993                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 7994            );
 7995            assert_eq!(
 7996                view.selections.display_ranges(cx),
 7997                vec![
 7998                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 7999                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8000                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8001                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8002                ]
 8003            );
 8004        });
 8005
 8006        view.update(cx, |view, cx| {
 8007            view.move_line_down(&MoveLineDown, cx);
 8008            assert_eq!(
 8009                view.display_text(cx),
 8010                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8011            );
 8012            assert_eq!(
 8013                view.selections.display_ranges(cx),
 8014                vec![
 8015                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8016                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8017                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8018                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8019                ]
 8020            );
 8021        });
 8022
 8023        view.update(cx, |view, cx| {
 8024            view.move_line_up(&MoveLineUp, cx);
 8025            assert_eq!(
 8026                view.display_text(cx),
 8027                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8028            );
 8029            assert_eq!(
 8030                view.selections.display_ranges(cx),
 8031                vec![
 8032                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8033                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8034                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8035                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8036                ]
 8037            );
 8038        });
 8039    }
 8040
 8041    #[gpui::test]
 8042    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8043        cx.set_global(Settings::test(cx));
 8044        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8045        let snapshot = buffer.read(cx).snapshot(cx);
 8046        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8047        editor.update(cx, |editor, cx| {
 8048            editor.insert_blocks(
 8049                [BlockProperties {
 8050                    position: snapshot.anchor_after(Point::new(2, 0)),
 8051                    disposition: BlockDisposition::Below,
 8052                    height: 1,
 8053                    render: Arc::new(|_| Empty::new().boxed()),
 8054                }],
 8055                cx,
 8056            );
 8057            editor.change_selections(None, cx, |s| {
 8058                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8059            });
 8060            editor.move_line_down(&MoveLineDown, cx);
 8061        });
 8062    }
 8063
 8064    #[gpui::test]
 8065    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8066        cx.set_global(Settings::test(cx));
 8067
 8068        cx.add_window(Default::default(), |cx| {
 8069            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8070
 8071            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8072            editor.transpose(&Default::default(), cx);
 8073            assert_eq!(editor.text(cx), "bac");
 8074            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8075
 8076            editor.transpose(&Default::default(), cx);
 8077            assert_eq!(editor.text(cx), "bca");
 8078            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8079
 8080            editor.transpose(&Default::default(), cx);
 8081            assert_eq!(editor.text(cx), "bac");
 8082            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8083
 8084            editor
 8085        })
 8086        .1;
 8087
 8088        cx.add_window(Default::default(), |cx| {
 8089            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8090
 8091            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8092            editor.transpose(&Default::default(), cx);
 8093            assert_eq!(editor.text(cx), "acb\nde");
 8094            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8095
 8096            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8097            editor.transpose(&Default::default(), cx);
 8098            assert_eq!(editor.text(cx), "acbd\ne");
 8099            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8100
 8101            editor.transpose(&Default::default(), cx);
 8102            assert_eq!(editor.text(cx), "acbde\n");
 8103            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8104
 8105            editor.transpose(&Default::default(), cx);
 8106            assert_eq!(editor.text(cx), "acbd\ne");
 8107            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8108
 8109            editor
 8110        })
 8111        .1;
 8112
 8113        cx.add_window(Default::default(), |cx| {
 8114            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8115
 8116            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8117            editor.transpose(&Default::default(), cx);
 8118            assert_eq!(editor.text(cx), "bacd\ne");
 8119            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8120
 8121            editor.transpose(&Default::default(), cx);
 8122            assert_eq!(editor.text(cx), "bcade\n");
 8123            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8124
 8125            editor.transpose(&Default::default(), cx);
 8126            assert_eq!(editor.text(cx), "bcda\ne");
 8127            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8128
 8129            editor.transpose(&Default::default(), cx);
 8130            assert_eq!(editor.text(cx), "bcade\n");
 8131            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8132
 8133            editor.transpose(&Default::default(), cx);
 8134            assert_eq!(editor.text(cx), "bcaed\n");
 8135            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8136
 8137            editor
 8138        })
 8139        .1;
 8140
 8141        cx.add_window(Default::default(), |cx| {
 8142            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8143
 8144            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8145            editor.transpose(&Default::default(), cx);
 8146            assert_eq!(editor.text(cx), "🏀🍐✋");
 8147            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8148
 8149            editor.transpose(&Default::default(), cx);
 8150            assert_eq!(editor.text(cx), "🏀✋🍐");
 8151            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8152
 8153            editor.transpose(&Default::default(), cx);
 8154            assert_eq!(editor.text(cx), "🏀🍐✋");
 8155            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8156
 8157            editor
 8158        })
 8159        .1;
 8160    }
 8161
 8162    #[gpui::test]
 8163    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8164        let mut cx = EditorTestContext::new(cx).await;
 8165
 8166        cx.set_state("[one✅ }two [three }four [five }six ");
 8167        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8168        cx.assert_editor_state("|two |four |six ");
 8169
 8170        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8171        cx.set_state("two |four |six |");
 8172        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8173        cx.assert_editor_state("two one✅ |four three |six five |");
 8174
 8175        // Paste again but with only two cursors. Since the number of cursors doesn't
 8176        // match the number of slices in the clipboard, the entire clipboard text
 8177        // is pasted at each cursor.
 8178        cx.set_state("|two one✅ four three six five |");
 8179        cx.update_editor(|e, cx| {
 8180            e.handle_input(&Input("( ".into()), cx);
 8181            e.paste(&Paste, cx);
 8182            e.handle_input(&Input(") ".into()), cx);
 8183        });
 8184        cx.assert_editor_state(indoc! {"
 8185            ( one✅ 
 8186            three 
 8187            five ) |two one✅ four three six five ( one✅ 
 8188            three 
 8189            five ) |"});
 8190
 8191        // Cut with three selections, one of which is full-line.
 8192        cx.set_state(indoc! {"
 8193            1[2}3
 8194            4|567
 8195            [8}9"});
 8196        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8197        cx.assert_editor_state(indoc! {"
 8198            1|3
 8199            |9"});
 8200
 8201        // Paste with three selections, noticing how the copied selection that was full-line
 8202        // gets inserted before the second cursor.
 8203        cx.set_state(indoc! {"
 8204            1|3
 8205            9|
 8206            [o}ne"});
 8207        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8208        cx.assert_editor_state(indoc! {"
 8209            12|3
 8210            4567
 8211            9|
 8212            8|ne"});
 8213
 8214        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8215        cx.set_state(indoc! {"
 8216            The quick brown
 8217            fox ju|mps over
 8218            the lazy dog"});
 8219        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8220        cx.assert_clipboard_content(Some("fox jumps over\n"));
 8221
 8222        // Paste with three selections, noticing how the copied full-line selection is inserted
 8223        // before the empty selections but replaces the selection that is non-empty.
 8224        cx.set_state(indoc! {"
 8225            T|he quick brown
 8226            [fo}x jumps over
 8227            t|he lazy dog"});
 8228        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8229        cx.assert_editor_state(indoc! {"
 8230            fox jumps over
 8231            T|he quick brown
 8232            fox jumps over
 8233            |x jumps over
 8234            fox jumps over
 8235            t|he lazy dog"});
 8236    }
 8237
 8238    #[gpui::test]
 8239    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8240        cx.set_global(Settings::test(cx));
 8241        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8242        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8243        view.update(cx, |view, cx| {
 8244            view.select_all(&SelectAll, cx);
 8245            assert_eq!(
 8246                view.selections.display_ranges(cx),
 8247                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8248            );
 8249        });
 8250    }
 8251
 8252    #[gpui::test]
 8253    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8254        cx.set_global(Settings::test(cx));
 8255        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8256        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8257        view.update(cx, |view, cx| {
 8258            view.change_selections(None, cx, |s| {
 8259                s.select_display_ranges([
 8260                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8261                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8262                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8263                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8264                ])
 8265            });
 8266            view.select_line(&SelectLine, cx);
 8267            assert_eq!(
 8268                view.selections.display_ranges(cx),
 8269                vec![
 8270                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8271                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8272                ]
 8273            );
 8274        });
 8275
 8276        view.update(cx, |view, cx| {
 8277            view.select_line(&SelectLine, cx);
 8278            assert_eq!(
 8279                view.selections.display_ranges(cx),
 8280                vec![
 8281                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8282                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8283                ]
 8284            );
 8285        });
 8286
 8287        view.update(cx, |view, cx| {
 8288            view.select_line(&SelectLine, cx);
 8289            assert_eq!(
 8290                view.selections.display_ranges(cx),
 8291                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8292            );
 8293        });
 8294    }
 8295
 8296    #[gpui::test]
 8297    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8298        cx.set_global(Settings::test(cx));
 8299        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8300        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8301        view.update(cx, |view, cx| {
 8302            view.fold_ranges(
 8303                vec![
 8304                    Point::new(0, 2)..Point::new(1, 2),
 8305                    Point::new(2, 3)..Point::new(4, 1),
 8306                    Point::new(7, 0)..Point::new(8, 4),
 8307                ],
 8308                cx,
 8309            );
 8310            view.change_selections(None, cx, |s| {
 8311                s.select_display_ranges([
 8312                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8313                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8314                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8315                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8316                ])
 8317            });
 8318            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8319        });
 8320
 8321        view.update(cx, |view, cx| {
 8322            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8323            assert_eq!(
 8324                view.display_text(cx),
 8325                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8326            );
 8327            assert_eq!(
 8328                view.selections.display_ranges(cx),
 8329                [
 8330                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8331                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8332                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8333                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8334                ]
 8335            );
 8336        });
 8337
 8338        view.update(cx, |view, cx| {
 8339            view.change_selections(None, cx, |s| {
 8340                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 8341            });
 8342            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8343            assert_eq!(
 8344                view.display_text(cx),
 8345                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8346            );
 8347            assert_eq!(
 8348                view.selections.display_ranges(cx),
 8349                [
 8350                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8351                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8352                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8353                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8354                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8355                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8356                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8357                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8358                ]
 8359            );
 8360        });
 8361    }
 8362
 8363    #[gpui::test]
 8364    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8365        cx.set_global(Settings::test(cx));
 8366        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8367        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8368
 8369        view.update(cx, |view, cx| {
 8370            view.change_selections(None, cx, |s| {
 8371                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 8372            });
 8373        });
 8374        view.update(cx, |view, cx| {
 8375            view.add_selection_above(&AddSelectionAbove, cx);
 8376            assert_eq!(
 8377                view.selections.display_ranges(cx),
 8378                vec![
 8379                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8380                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8381                ]
 8382            );
 8383        });
 8384
 8385        view.update(cx, |view, cx| {
 8386            view.add_selection_above(&AddSelectionAbove, cx);
 8387            assert_eq!(
 8388                view.selections.display_ranges(cx),
 8389                vec![
 8390                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8391                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8392                ]
 8393            );
 8394        });
 8395
 8396        view.update(cx, |view, cx| {
 8397            view.add_selection_below(&AddSelectionBelow, cx);
 8398            assert_eq!(
 8399                view.selections.display_ranges(cx),
 8400                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8401            );
 8402
 8403            view.undo_selection(&UndoSelection, cx);
 8404            assert_eq!(
 8405                view.selections.display_ranges(cx),
 8406                vec![
 8407                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8408                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8409                ]
 8410            );
 8411
 8412            view.redo_selection(&RedoSelection, cx);
 8413            assert_eq!(
 8414                view.selections.display_ranges(cx),
 8415                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8416            );
 8417        });
 8418
 8419        view.update(cx, |view, cx| {
 8420            view.add_selection_below(&AddSelectionBelow, cx);
 8421            assert_eq!(
 8422                view.selections.display_ranges(cx),
 8423                vec![
 8424                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8425                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8426                ]
 8427            );
 8428        });
 8429
 8430        view.update(cx, |view, cx| {
 8431            view.add_selection_below(&AddSelectionBelow, cx);
 8432            assert_eq!(
 8433                view.selections.display_ranges(cx),
 8434                vec![
 8435                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8436                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8437                ]
 8438            );
 8439        });
 8440
 8441        view.update(cx, |view, cx| {
 8442            view.change_selections(None, cx, |s| {
 8443                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 8444            });
 8445        });
 8446        view.update(cx, |view, cx| {
 8447            view.add_selection_below(&AddSelectionBelow, cx);
 8448            assert_eq!(
 8449                view.selections.display_ranges(cx),
 8450                vec![
 8451                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8452                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8453                ]
 8454            );
 8455        });
 8456
 8457        view.update(cx, |view, cx| {
 8458            view.add_selection_below(&AddSelectionBelow, cx);
 8459            assert_eq!(
 8460                view.selections.display_ranges(cx),
 8461                vec![
 8462                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8463                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8464                ]
 8465            );
 8466        });
 8467
 8468        view.update(cx, |view, cx| {
 8469            view.add_selection_above(&AddSelectionAbove, cx);
 8470            assert_eq!(
 8471                view.selections.display_ranges(cx),
 8472                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8473            );
 8474        });
 8475
 8476        view.update(cx, |view, cx| {
 8477            view.add_selection_above(&AddSelectionAbove, cx);
 8478            assert_eq!(
 8479                view.selections.display_ranges(cx),
 8480                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8481            );
 8482        });
 8483
 8484        view.update(cx, |view, cx| {
 8485            view.change_selections(None, cx, |s| {
 8486                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 8487            });
 8488            view.add_selection_below(&AddSelectionBelow, cx);
 8489            assert_eq!(
 8490                view.selections.display_ranges(cx),
 8491                vec![
 8492                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8493                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8494                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8495                ]
 8496            );
 8497        });
 8498
 8499        view.update(cx, |view, cx| {
 8500            view.add_selection_below(&AddSelectionBelow, cx);
 8501            assert_eq!(
 8502                view.selections.display_ranges(cx),
 8503                vec![
 8504                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8505                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8506                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8507                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8508                ]
 8509            );
 8510        });
 8511
 8512        view.update(cx, |view, cx| {
 8513            view.add_selection_above(&AddSelectionAbove, cx);
 8514            assert_eq!(
 8515                view.selections.display_ranges(cx),
 8516                vec![
 8517                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8518                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8519                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8520                ]
 8521            );
 8522        });
 8523
 8524        view.update(cx, |view, cx| {
 8525            view.change_selections(None, cx, |s| {
 8526                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 8527            });
 8528        });
 8529        view.update(cx, |view, cx| {
 8530            view.add_selection_above(&AddSelectionAbove, cx);
 8531            assert_eq!(
 8532                view.selections.display_ranges(cx),
 8533                vec![
 8534                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8535                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8536                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8537                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8538                ]
 8539            );
 8540        });
 8541
 8542        view.update(cx, |view, cx| {
 8543            view.add_selection_below(&AddSelectionBelow, cx);
 8544            assert_eq!(
 8545                view.selections.display_ranges(cx),
 8546                vec![
 8547                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8548                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8549                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8550                ]
 8551            );
 8552        });
 8553    }
 8554
 8555    #[gpui::test]
 8556    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8557        cx.set_global(Settings::test(cx));
 8558
 8559        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8560        let buffer = MultiBuffer::build_simple(&text, cx);
 8561        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8562
 8563        view.update(cx, |view, cx| {
 8564            view.change_selections(None, cx, |s| {
 8565                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 8566            });
 8567            view.select_next(
 8568                &SelectNext {
 8569                    replace_newest: false,
 8570                },
 8571                cx,
 8572            );
 8573            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8574
 8575            view.select_next(
 8576                &SelectNext {
 8577                    replace_newest: false,
 8578                },
 8579                cx,
 8580            );
 8581            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8582
 8583            view.undo_selection(&UndoSelection, cx);
 8584            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8585
 8586            view.redo_selection(&RedoSelection, cx);
 8587            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8588
 8589            view.select_next(
 8590                &SelectNext {
 8591                    replace_newest: false,
 8592                },
 8593                cx,
 8594            );
 8595            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 8596
 8597            view.select_next(
 8598                &SelectNext {
 8599                    replace_newest: false,
 8600                },
 8601                cx,
 8602            );
 8603            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 8604        });
 8605    }
 8606
 8607    #[gpui::test]
 8608    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8609        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8610        let language = Arc::new(Language::new(
 8611            LanguageConfig::default(),
 8612            Some(tree_sitter_rust::language()),
 8613        ));
 8614
 8615        let text = r#"
 8616            use mod1::mod2::{mod3, mod4};
 8617
 8618            fn fn_1(param1: bool, param2: &str) {
 8619                let var1 = "text";
 8620            }
 8621        "#
 8622        .unindent();
 8623
 8624        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8625        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8626        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8627        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8628            .await;
 8629
 8630        view.update(cx, |view, cx| {
 8631            view.change_selections(None, cx, |s| {
 8632                s.select_display_ranges([
 8633                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8634                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8635                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8636                ]);
 8637            });
 8638            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8639        });
 8640        assert_eq!(
 8641            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 8642            &[
 8643                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8644                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8645                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8646            ]
 8647        );
 8648
 8649        view.update(cx, |view, cx| {
 8650            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8651        });
 8652        assert_eq!(
 8653            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8654            &[
 8655                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8656                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8657            ]
 8658        );
 8659
 8660        view.update(cx, |view, cx| {
 8661            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8662        });
 8663        assert_eq!(
 8664            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8665            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8666        );
 8667
 8668        // Trying to expand the selected syntax node one more time has no effect.
 8669        view.update(cx, |view, cx| {
 8670            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8671        });
 8672        assert_eq!(
 8673            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8674            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8675        );
 8676
 8677        view.update(cx, |view, cx| {
 8678            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8679        });
 8680        assert_eq!(
 8681            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8682            &[
 8683                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8684                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8685            ]
 8686        );
 8687
 8688        view.update(cx, |view, cx| {
 8689            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8690        });
 8691        assert_eq!(
 8692            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8693            &[
 8694                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8695                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8696                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8697            ]
 8698        );
 8699
 8700        view.update(cx, |view, cx| {
 8701            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8702        });
 8703        assert_eq!(
 8704            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8705            &[
 8706                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8707                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8708                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8709            ]
 8710        );
 8711
 8712        // Trying to shrink the selected syntax node one more time has no effect.
 8713        view.update(cx, |view, cx| {
 8714            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8715        });
 8716        assert_eq!(
 8717            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8718            &[
 8719                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8720                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8721                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8722            ]
 8723        );
 8724
 8725        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8726        // a fold.
 8727        view.update(cx, |view, cx| {
 8728            view.fold_ranges(
 8729                vec![
 8730                    Point::new(0, 21)..Point::new(0, 24),
 8731                    Point::new(3, 20)..Point::new(3, 22),
 8732                ],
 8733                cx,
 8734            );
 8735            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8736        });
 8737        assert_eq!(
 8738            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8739            &[
 8740                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8741                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8742                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8743            ]
 8744        );
 8745    }
 8746
 8747    #[gpui::test]
 8748    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8749        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8750        let language = Arc::new(
 8751            Language::new(
 8752                LanguageConfig {
 8753                    brackets: vec![
 8754                        BracketPair {
 8755                            start: "{".to_string(),
 8756                            end: "}".to_string(),
 8757                            close: false,
 8758                            newline: true,
 8759                        },
 8760                        BracketPair {
 8761                            start: "(".to_string(),
 8762                            end: ")".to_string(),
 8763                            close: false,
 8764                            newline: true,
 8765                        },
 8766                    ],
 8767                    ..Default::default()
 8768                },
 8769                Some(tree_sitter_rust::language()),
 8770            )
 8771            .with_indents_query(
 8772                r#"
 8773                (_ "(" ")" @end) @indent
 8774                (_ "{" "}" @end) @indent
 8775                "#,
 8776            )
 8777            .unwrap(),
 8778        );
 8779
 8780        let text = "fn a() {}";
 8781
 8782        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8783        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8784        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8785        editor
 8786            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8787            .await;
 8788
 8789        editor.update(cx, |editor, cx| {
 8790            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 8791            editor.newline(&Newline, cx);
 8792            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8793            assert_eq!(
 8794                editor.selections.ranges(cx),
 8795                &[
 8796                    Point::new(1, 4)..Point::new(1, 4),
 8797                    Point::new(3, 4)..Point::new(3, 4),
 8798                    Point::new(5, 0)..Point::new(5, 0)
 8799                ]
 8800            );
 8801        });
 8802    }
 8803
 8804    #[gpui::test]
 8805    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8806        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8807        let language = Arc::new(Language::new(
 8808            LanguageConfig {
 8809                brackets: vec![
 8810                    BracketPair {
 8811                        start: "{".to_string(),
 8812                        end: "}".to_string(),
 8813                        close: true,
 8814                        newline: true,
 8815                    },
 8816                    BracketPair {
 8817                        start: "/*".to_string(),
 8818                        end: " */".to_string(),
 8819                        close: true,
 8820                        newline: true,
 8821                    },
 8822                ],
 8823                autoclose_before: "})]".to_string(),
 8824                ..Default::default()
 8825            },
 8826            Some(tree_sitter_rust::language()),
 8827        ));
 8828
 8829        let text = r#"
 8830            a
 8831
 8832            /
 8833
 8834        "#
 8835        .unindent();
 8836
 8837        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8838        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8839        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8840        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8841            .await;
 8842
 8843        view.update(cx, |view, cx| {
 8844            view.change_selections(None, cx, |s| {
 8845                s.select_display_ranges([
 8846                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8847                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8848                ])
 8849            });
 8850
 8851            view.handle_input(&Input("{".to_string()), cx);
 8852            view.handle_input(&Input("{".to_string()), cx);
 8853            view.handle_input(&Input("{".to_string()), cx);
 8854            assert_eq!(
 8855                view.text(cx),
 8856                "
 8857                {{{}}}
 8858                {{{}}}
 8859                /
 8860
 8861                "
 8862                .unindent()
 8863            );
 8864
 8865            view.move_right(&MoveRight, cx);
 8866            view.handle_input(&Input("}".to_string()), cx);
 8867            view.handle_input(&Input("}".to_string()), cx);
 8868            view.handle_input(&Input("}".to_string()), cx);
 8869            assert_eq!(
 8870                view.text(cx),
 8871                "
 8872                {{{}}}}
 8873                {{{}}}}
 8874                /
 8875
 8876                "
 8877                .unindent()
 8878            );
 8879
 8880            view.undo(&Undo, cx);
 8881            view.handle_input(&Input("/".to_string()), cx);
 8882            view.handle_input(&Input("*".to_string()), cx);
 8883            assert_eq!(
 8884                view.text(cx),
 8885                "
 8886                /* */
 8887                /* */
 8888                /
 8889
 8890                "
 8891                .unindent()
 8892            );
 8893
 8894            view.undo(&Undo, cx);
 8895            view.change_selections(None, cx, |s| {
 8896                s.select_display_ranges([
 8897                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8898                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8899                ])
 8900            });
 8901            view.handle_input(&Input("*".to_string()), cx);
 8902            assert_eq!(
 8903                view.text(cx),
 8904                "
 8905                a
 8906
 8907                /*
 8908                *
 8909                "
 8910                .unindent()
 8911            );
 8912
 8913            // Don't autoclose if the next character isn't whitespace and isn't
 8914            // listed in the language's "autoclose_before" section.
 8915            view.finalize_last_transaction(cx);
 8916            view.change_selections(None, cx, |s| {
 8917                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 8918            });
 8919            view.handle_input(&Input("{".to_string()), cx);
 8920            assert_eq!(
 8921                view.text(cx),
 8922                "
 8923                {a
 8924
 8925                /*
 8926                *
 8927                "
 8928                .unindent()
 8929            );
 8930
 8931            view.undo(&Undo, cx);
 8932            view.change_selections(None, cx, |s| {
 8933                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 8934            });
 8935            view.handle_input(&Input("{".to_string()), cx);
 8936            assert_eq!(
 8937                view.text(cx),
 8938                "
 8939                {a}
 8940
 8941                /*
 8942                *
 8943                "
 8944                .unindent()
 8945            );
 8946            assert_eq!(
 8947                view.selections.display_ranges(cx),
 8948                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8949            );
 8950        });
 8951    }
 8952
 8953    #[gpui::test]
 8954    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 8955        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8956
 8957        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 8958            a.| b
 8959            a.| b
 8960            a.| b"});
 8961        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 8962        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8963
 8964        editor.update(cx, |editor, cx| {
 8965            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 8966
 8967            editor
 8968                .insert_snippet(&insertion_ranges, snippet, cx)
 8969                .unwrap();
 8970
 8971            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 8972                let range_markers = ('<', '>');
 8973                let (expected_text, mut selection_ranges_lookup) =
 8974                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 8975                let selection_ranges = selection_ranges_lookup
 8976                    .remove(&range_markers.into())
 8977                    .unwrap();
 8978                assert_eq!(editor.text(cx), expected_text);
 8979                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 8980            }
 8981            assert(
 8982                editor,
 8983                cx,
 8984                indoc! {"
 8985                    a.f(<one>, two, <three>) b
 8986                    a.f(<one>, two, <three>) b
 8987                    a.f(<one>, two, <three>) b"},
 8988            );
 8989
 8990            // Can't move earlier than the first tab stop
 8991            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 8992            assert(
 8993                editor,
 8994                cx,
 8995                indoc! {"
 8996                    a.f(<one>, two, <three>) b
 8997                    a.f(<one>, two, <three>) b
 8998                    a.f(<one>, two, <three>) b"},
 8999            );
 9000
 9001            assert!(editor.move_to_next_snippet_tabstop(cx));
 9002            assert(
 9003                editor,
 9004                cx,
 9005                indoc! {"
 9006                    a.f(one, <two>, three) b
 9007                    a.f(one, <two>, three) b
 9008                    a.f(one, <two>, three) b"},
 9009            );
 9010
 9011            editor.move_to_prev_snippet_tabstop(cx);
 9012            assert(
 9013                editor,
 9014                cx,
 9015                indoc! {"
 9016                    a.f(<one>, two, <three>) b
 9017                    a.f(<one>, two, <three>) b
 9018                    a.f(<one>, two, <three>) b"},
 9019            );
 9020
 9021            assert!(editor.move_to_next_snippet_tabstop(cx));
 9022            assert(
 9023                editor,
 9024                cx,
 9025                indoc! {"
 9026                    a.f(one, <two>, three) b
 9027                    a.f(one, <two>, three) b
 9028                    a.f(one, <two>, three) b"},
 9029            );
 9030            assert!(editor.move_to_next_snippet_tabstop(cx));
 9031            assert(
 9032                editor,
 9033                cx,
 9034                indoc! {"
 9035                    a.f(one, two, three)<> b
 9036                    a.f(one, two, three)<> b
 9037                    a.f(one, two, three)<> b"},
 9038            );
 9039
 9040            // As soon as the last tab stop is reached, snippet state is gone
 9041            editor.move_to_prev_snippet_tabstop(cx);
 9042            assert(
 9043                editor,
 9044                cx,
 9045                indoc! {"
 9046                    a.f(one, two, three)<> b
 9047                    a.f(one, two, three)<> b
 9048                    a.f(one, two, three)<> b"},
 9049            );
 9050        });
 9051    }
 9052
 9053    #[gpui::test]
 9054    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9055        cx.foreground().forbid_parking();
 9056        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9057
 9058        let mut language = Language::new(
 9059            LanguageConfig {
 9060                name: "Rust".into(),
 9061                path_suffixes: vec!["rs".to_string()],
 9062                ..Default::default()
 9063            },
 9064            Some(tree_sitter_rust::language()),
 9065        );
 9066        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9067            capabilities: lsp::ServerCapabilities {
 9068                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9069                ..Default::default()
 9070            },
 9071            ..Default::default()
 9072        });
 9073
 9074        let fs = FakeFs::new(cx.background().clone());
 9075        fs.insert_file("/file.rs", Default::default()).await;
 9076
 9077        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9078        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9079        let buffer = project
 9080            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9081            .await
 9082            .unwrap();
 9083
 9084        cx.foreground().start_waiting();
 9085        let fake_server = fake_servers.next().await.unwrap();
 9086
 9087        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9088        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9089        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9090        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9091
 9092        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9093        fake_server
 9094            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9095                assert_eq!(
 9096                    params.text_document.uri,
 9097                    lsp::Url::from_file_path("/file.rs").unwrap()
 9098                );
 9099                assert_eq!(params.options.tab_size, 4);
 9100                Ok(Some(vec![lsp::TextEdit::new(
 9101                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9102                    ", ".to_string(),
 9103                )]))
 9104            })
 9105            .next()
 9106            .await;
 9107        cx.foreground().start_waiting();
 9108        save.await.unwrap();
 9109        assert_eq!(
 9110            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9111            "one, two\nthree\n"
 9112        );
 9113        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9114
 9115        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9116        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9117
 9118        // Ensure we can still save even if formatting hangs.
 9119        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9120            assert_eq!(
 9121                params.text_document.uri,
 9122                lsp::Url::from_file_path("/file.rs").unwrap()
 9123            );
 9124            futures::future::pending::<()>().await;
 9125            unreachable!()
 9126        });
 9127        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9128        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9129        cx.foreground().start_waiting();
 9130        save.await.unwrap();
 9131        assert_eq!(
 9132            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9133            "one\ntwo\nthree\n"
 9134        );
 9135        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9136
 9137        // Set rust language override and assert overriden tabsize is sent to language server
 9138        cx.update(|cx| {
 9139            cx.update_global::<Settings, _, _>(|settings, _| {
 9140                settings.language_overrides.insert(
 9141                    "Rust".into(),
 9142                    LanguageOverride {
 9143                        tab_size: Some(8),
 9144                        ..Default::default()
 9145                    },
 9146                );
 9147            })
 9148        });
 9149
 9150        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9151        fake_server
 9152            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9153                assert_eq!(
 9154                    params.text_document.uri,
 9155                    lsp::Url::from_file_path("/file.rs").unwrap()
 9156                );
 9157                assert_eq!(params.options.tab_size, 8);
 9158                Ok(Some(vec![]))
 9159            })
 9160            .next()
 9161            .await;
 9162        cx.foreground().start_waiting();
 9163        save.await.unwrap();
 9164    }
 9165
 9166    #[gpui::test]
 9167    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
 9168        cx.foreground().forbid_parking();
 9169        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9170
 9171        let mut language = Language::new(
 9172            LanguageConfig {
 9173                name: "Rust".into(),
 9174                path_suffixes: vec!["rs".to_string()],
 9175                ..Default::default()
 9176            },
 9177            Some(tree_sitter_rust::language()),
 9178        );
 9179        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9180            capabilities: lsp::ServerCapabilities {
 9181                document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
 9182                ..Default::default()
 9183            },
 9184            ..Default::default()
 9185        });
 9186
 9187        let fs = FakeFs::new(cx.background().clone());
 9188        fs.insert_file("/file.rs", Default::default()).await;
 9189
 9190        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9191        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9192        let buffer = project
 9193            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9194            .await
 9195            .unwrap();
 9196
 9197        cx.foreground().start_waiting();
 9198        let fake_server = fake_servers.next().await.unwrap();
 9199
 9200        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9201        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9202        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9203        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9204
 9205        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9206        fake_server
 9207            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9208                assert_eq!(
 9209                    params.text_document.uri,
 9210                    lsp::Url::from_file_path("/file.rs").unwrap()
 9211                );
 9212                assert_eq!(params.options.tab_size, 4);
 9213                Ok(Some(vec![lsp::TextEdit::new(
 9214                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9215                    ", ".to_string(),
 9216                )]))
 9217            })
 9218            .next()
 9219            .await;
 9220        cx.foreground().start_waiting();
 9221        save.await.unwrap();
 9222        assert_eq!(
 9223            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9224            "one, two\nthree\n"
 9225        );
 9226        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9227
 9228        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9229        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9230
 9231        // Ensure we can still save even if formatting hangs.
 9232        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
 9233            move |params, _| async move {
 9234                assert_eq!(
 9235                    params.text_document.uri,
 9236                    lsp::Url::from_file_path("/file.rs").unwrap()
 9237                );
 9238                futures::future::pending::<()>().await;
 9239                unreachable!()
 9240            },
 9241        );
 9242        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9243        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9244        cx.foreground().start_waiting();
 9245        save.await.unwrap();
 9246        assert_eq!(
 9247            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9248            "one\ntwo\nthree\n"
 9249        );
 9250        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9251
 9252        // Set rust language override and assert overriden tabsize is sent to language server
 9253        cx.update(|cx| {
 9254            cx.update_global::<Settings, _, _>(|settings, _| {
 9255                settings.language_overrides.insert(
 9256                    "Rust".into(),
 9257                    LanguageOverride {
 9258                        tab_size: Some(8),
 9259                        ..Default::default()
 9260                    },
 9261                );
 9262            })
 9263        });
 9264
 9265        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9266        fake_server
 9267            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9268                assert_eq!(
 9269                    params.text_document.uri,
 9270                    lsp::Url::from_file_path("/file.rs").unwrap()
 9271                );
 9272                assert_eq!(params.options.tab_size, 8);
 9273                Ok(Some(vec![]))
 9274            })
 9275            .next()
 9276            .await;
 9277        cx.foreground().start_waiting();
 9278        save.await.unwrap();
 9279    }
 9280
 9281    #[gpui::test]
 9282    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9283        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9284
 9285        let mut language = Language::new(
 9286            LanguageConfig {
 9287                name: "Rust".into(),
 9288                path_suffixes: vec!["rs".to_string()],
 9289                ..Default::default()
 9290            },
 9291            Some(tree_sitter_rust::language()),
 9292        );
 9293        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9294            capabilities: lsp::ServerCapabilities {
 9295                completion_provider: Some(lsp::CompletionOptions {
 9296                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9297                    ..Default::default()
 9298                }),
 9299                ..Default::default()
 9300            },
 9301            ..Default::default()
 9302        });
 9303
 9304        let text = "
 9305            one
 9306            two
 9307            three
 9308        "
 9309        .unindent();
 9310
 9311        let fs = FakeFs::new(cx.background().clone());
 9312        fs.insert_file("/file.rs", text).await;
 9313
 9314        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9315        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9316        let buffer = project
 9317            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9318            .await
 9319            .unwrap();
 9320        let mut fake_server = fake_servers.next().await.unwrap();
 9321
 9322        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9323        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9324
 9325        editor.update(cx, |editor, cx| {
 9326            editor.project = Some(project);
 9327            editor.change_selections(None, cx, |s| {
 9328                s.select_ranges([Point::new(0, 3)..Point::new(0, 3)])
 9329            });
 9330            editor.handle_input(&Input(".".to_string()), cx);
 9331        });
 9332
 9333        handle_completion_request(
 9334            &mut fake_server,
 9335            "/file.rs",
 9336            Point::new(0, 4),
 9337            vec![
 9338                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9339                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9340            ],
 9341        )
 9342        .await;
 9343        editor
 9344            .condition(&cx, |editor, _| editor.context_menu_visible())
 9345            .await;
 9346
 9347        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9348            editor.move_down(&MoveDown, cx);
 9349            let apply_additional_edits = editor
 9350                .confirm_completion(&ConfirmCompletion::default(), cx)
 9351                .unwrap();
 9352            assert_eq!(
 9353                editor.text(cx),
 9354                "
 9355                    one.second_completion
 9356                    two
 9357                    three
 9358                "
 9359                .unindent()
 9360            );
 9361            apply_additional_edits
 9362        });
 9363
 9364        handle_resolve_completion_request(
 9365            &mut fake_server,
 9366            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9367        )
 9368        .await;
 9369        apply_additional_edits.await.unwrap();
 9370        assert_eq!(
 9371            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9372            "
 9373                one.second_completion
 9374                two
 9375                three
 9376                additional edit
 9377            "
 9378            .unindent()
 9379        );
 9380
 9381        editor.update(cx, |editor, cx| {
 9382            editor.change_selections(None, cx, |s| {
 9383                s.select_ranges([
 9384                    Point::new(1, 3)..Point::new(1, 3),
 9385                    Point::new(2, 5)..Point::new(2, 5),
 9386                ])
 9387            });
 9388
 9389            editor.handle_input(&Input(" ".to_string()), cx);
 9390            assert!(editor.context_menu.is_none());
 9391            editor.handle_input(&Input("s".to_string()), cx);
 9392            assert!(editor.context_menu.is_none());
 9393        });
 9394
 9395        handle_completion_request(
 9396            &mut fake_server,
 9397            "/file.rs",
 9398            Point::new(2, 7),
 9399            vec![
 9400                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9401                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9402                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9403            ],
 9404        )
 9405        .await;
 9406        editor
 9407            .condition(&cx, |editor, _| editor.context_menu_visible())
 9408            .await;
 9409
 9410        editor.update(cx, |editor, cx| {
 9411            editor.handle_input(&Input("i".to_string()), cx);
 9412        });
 9413
 9414        handle_completion_request(
 9415            &mut fake_server,
 9416            "/file.rs",
 9417            Point::new(2, 8),
 9418            vec![
 9419                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9420                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9421                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9422            ],
 9423        )
 9424        .await;
 9425        editor
 9426            .condition(&cx, |editor, _| editor.context_menu_visible())
 9427            .await;
 9428
 9429        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9430            let apply_additional_edits = editor
 9431                .confirm_completion(&ConfirmCompletion::default(), cx)
 9432                .unwrap();
 9433            assert_eq!(
 9434                editor.text(cx),
 9435                "
 9436                    one.second_completion
 9437                    two sixth_completion
 9438                    three sixth_completion
 9439                    additional edit
 9440                "
 9441                .unindent()
 9442            );
 9443            apply_additional_edits
 9444        });
 9445        handle_resolve_completion_request(&mut fake_server, None).await;
 9446        apply_additional_edits.await.unwrap();
 9447
 9448        async fn handle_completion_request(
 9449            fake: &mut FakeLanguageServer,
 9450            path: &'static str,
 9451            position: Point,
 9452            completions: Vec<(Range<Point>, &'static str)>,
 9453        ) {
 9454            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9455                let completions = completions.clone();
 9456                async move {
 9457                    assert_eq!(
 9458                        params.text_document_position.text_document.uri,
 9459                        lsp::Url::from_file_path(path).unwrap()
 9460                    );
 9461                    assert_eq!(
 9462                        params.text_document_position.position,
 9463                        lsp::Position::new(position.row, position.column)
 9464                    );
 9465                    Ok(Some(lsp::CompletionResponse::Array(
 9466                        completions
 9467                            .iter()
 9468                            .map(|(range, new_text)| lsp::CompletionItem {
 9469                                label: new_text.to_string(),
 9470                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9471                                    range: lsp::Range::new(
 9472                                        lsp::Position::new(range.start.row, range.start.column),
 9473                                        lsp::Position::new(range.start.row, range.start.column),
 9474                                    ),
 9475                                    new_text: new_text.to_string(),
 9476                                })),
 9477                                ..Default::default()
 9478                            })
 9479                            .collect(),
 9480                    )))
 9481                }
 9482            })
 9483            .next()
 9484            .await;
 9485        }
 9486
 9487        async fn handle_resolve_completion_request(
 9488            fake: &mut FakeLanguageServer,
 9489            edit: Option<(Range<Point>, &'static str)>,
 9490        ) {
 9491            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9492                let edit = edit.clone();
 9493                async move {
 9494                    Ok(lsp::CompletionItem {
 9495                        additional_text_edits: edit.map(|(range, new_text)| {
 9496                            vec![lsp::TextEdit::new(
 9497                                lsp::Range::new(
 9498                                    lsp::Position::new(range.start.row, range.start.column),
 9499                                    lsp::Position::new(range.end.row, range.end.column),
 9500                                ),
 9501                                new_text.to_string(),
 9502                            )]
 9503                        }),
 9504                        ..Default::default()
 9505                    })
 9506                }
 9507            })
 9508            .next()
 9509            .await;
 9510        }
 9511    }
 9512
 9513    #[gpui::test]
 9514    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9515        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9516        let language = Arc::new(Language::new(
 9517            LanguageConfig {
 9518                line_comment: Some("// ".to_string()),
 9519                ..Default::default()
 9520            },
 9521            Some(tree_sitter_rust::language()),
 9522        ));
 9523
 9524        let text = "
 9525            fn a() {
 9526                //b();
 9527                // c();
 9528                //  d();
 9529            }
 9530        "
 9531        .unindent();
 9532
 9533        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9534        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9535        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9536
 9537        view.update(cx, |editor, cx| {
 9538            // If multiple selections intersect a line, the line is only
 9539            // toggled once.
 9540            editor.change_selections(None, cx, |s| {
 9541                s.select_display_ranges([
 9542                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9543                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9544                ])
 9545            });
 9546            editor.toggle_comments(&ToggleComments, cx);
 9547            assert_eq!(
 9548                editor.text(cx),
 9549                "
 9550                    fn a() {
 9551                        b();
 9552                        c();
 9553                         d();
 9554                    }
 9555                "
 9556                .unindent()
 9557            );
 9558
 9559            // The comment prefix is inserted at the same column for every line
 9560            // in a selection.
 9561            editor.change_selections(None, cx, |s| {
 9562                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
 9563            });
 9564            editor.toggle_comments(&ToggleComments, cx);
 9565            assert_eq!(
 9566                editor.text(cx),
 9567                "
 9568                    fn a() {
 9569                        // b();
 9570                        // c();
 9571                        //  d();
 9572                    }
 9573                "
 9574                .unindent()
 9575            );
 9576
 9577            // If a selection ends at the beginning of a line, that line is not toggled.
 9578            editor.change_selections(None, cx, |s| {
 9579                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
 9580            });
 9581            editor.toggle_comments(&ToggleComments, cx);
 9582            assert_eq!(
 9583                editor.text(cx),
 9584                "
 9585                        fn a() {
 9586                            // b();
 9587                            c();
 9588                            //  d();
 9589                        }
 9590                    "
 9591                .unindent()
 9592            );
 9593        });
 9594    }
 9595
 9596    #[gpui::test]
 9597    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9598        cx.set_global(Settings::test(cx));
 9599        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9600        let multibuffer = cx.add_model(|cx| {
 9601            let mut multibuffer = MultiBuffer::new(0);
 9602            multibuffer.push_excerpts(
 9603                buffer.clone(),
 9604                [
 9605                    ExcerptRange {
 9606                        context: Point::new(0, 0)..Point::new(0, 4),
 9607                        primary: None,
 9608                    },
 9609                    ExcerptRange {
 9610                        context: Point::new(1, 0)..Point::new(1, 4),
 9611                        primary: None,
 9612                    },
 9613                ],
 9614                cx,
 9615            );
 9616            multibuffer
 9617        });
 9618
 9619        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9620
 9621        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9622        view.update(cx, |view, cx| {
 9623            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9624            view.change_selections(None, cx, |s| {
 9625                s.select_ranges([
 9626                    Point::new(0, 0)..Point::new(0, 0),
 9627                    Point::new(1, 0)..Point::new(1, 0),
 9628                ])
 9629            });
 9630
 9631            view.handle_input(&Input("X".to_string()), cx);
 9632            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9633            assert_eq!(
 9634                view.selections.ranges(cx),
 9635                [
 9636                    Point::new(0, 1)..Point::new(0, 1),
 9637                    Point::new(1, 1)..Point::new(1, 1),
 9638                ]
 9639            )
 9640        });
 9641    }
 9642
 9643    #[gpui::test]
 9644    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9645        cx.set_global(Settings::test(cx));
 9646        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
 9647                [aaaa
 9648                (bbbb]
 9649                cccc)"});
 9650        let excerpt_ranges = excerpt_ranges
 9651            .into_iter()
 9652            .map(|context| ExcerptRange { context, primary: None });
 9653        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
 9654        let multibuffer = cx.add_model(|cx| {
 9655            let mut multibuffer = MultiBuffer::new(0);
 9656            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
 9657            multibuffer
 9658        });
 9659
 9660        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9661        view.update(cx, |view, cx| {
 9662            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
 9663                aaaa
 9664                b|bbb
 9665                b|bb|b
 9666                cccc"});
 9667            assert_eq!(view.text(cx), expected_text);
 9668            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
 9669
 9670            view.handle_input(&Input("X".to_string()), cx);
 9671
 9672            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9673                aaaa
 9674                bX|bbXb
 9675                bX|bbX|b
 9676                cccc"});
 9677            assert_eq!(view.text(cx), expected_text);
 9678            assert_eq!(view.selections.ranges(cx), expected_selections);
 9679
 9680            view.newline(&Newline, cx);
 9681            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9682                aaaa
 9683                bX
 9684                |bbX
 9685                b
 9686                bX
 9687                |bbX
 9688                |b
 9689                cccc"});
 9690            assert_eq!(view.text(cx), expected_text);
 9691            assert_eq!(view.selections.ranges(cx), expected_selections);
 9692        });
 9693    }
 9694
 9695    #[gpui::test]
 9696    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9697        cx.set_global(Settings::test(cx));
 9698        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9699        let mut excerpt1_id = None;
 9700        let multibuffer = cx.add_model(|cx| {
 9701            let mut multibuffer = MultiBuffer::new(0);
 9702            excerpt1_id = multibuffer
 9703                .push_excerpts(
 9704                    buffer.clone(),
 9705                    [
 9706                        ExcerptRange {
 9707                            context: Point::new(0, 0)..Point::new(1, 4),
 9708                            primary: None,
 9709                        },
 9710                        ExcerptRange {
 9711                            context: Point::new(1, 0)..Point::new(2, 4),
 9712                            primary: None,
 9713                        },
 9714                    ],
 9715                    cx,
 9716                )
 9717                .into_iter()
 9718                .next();
 9719            multibuffer
 9720        });
 9721        assert_eq!(
 9722            multibuffer.read(cx).read(cx).text(),
 9723            "aaaa\nbbbb\nbbbb\ncccc"
 9724        );
 9725        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9726            let mut editor = build_editor(multibuffer.clone(), cx);
 9727            let snapshot = editor.snapshot(cx);
 9728            editor.change_selections(None, cx, |s| {
 9729                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
 9730            });
 9731            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9732            assert_eq!(
 9733                editor.selections.ranges(cx),
 9734                [
 9735                    Point::new(1, 3)..Point::new(1, 3),
 9736                    Point::new(2, 1)..Point::new(2, 1),
 9737                ]
 9738            );
 9739            editor
 9740        });
 9741
 9742        // Refreshing selections is a no-op when excerpts haven't changed.
 9743        editor.update(cx, |editor, cx| {
 9744            editor.change_selections(None, cx, |s| {
 9745                s.refresh();
 9746            });
 9747            assert_eq!(
 9748                editor.selections.ranges(cx),
 9749                [
 9750                    Point::new(1, 3)..Point::new(1, 3),
 9751                    Point::new(2, 1)..Point::new(2, 1),
 9752                ]
 9753            );
 9754        });
 9755
 9756        multibuffer.update(cx, |multibuffer, cx| {
 9757            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9758        });
 9759        editor.update(cx, |editor, cx| {
 9760            // Removing an excerpt causes the first selection to become degenerate.
 9761            assert_eq!(
 9762                editor.selections.ranges(cx),
 9763                [
 9764                    Point::new(0, 0)..Point::new(0, 0),
 9765                    Point::new(0, 1)..Point::new(0, 1)
 9766                ]
 9767            );
 9768
 9769            // Refreshing selections will relocate the first selection to the original buffer
 9770            // location.
 9771            editor.change_selections(None, cx, |s| {
 9772                s.refresh();
 9773            });
 9774            assert_eq!(
 9775                editor.selections.ranges(cx),
 9776                [
 9777                    Point::new(0, 1)..Point::new(0, 1),
 9778                    Point::new(0, 3)..Point::new(0, 3)
 9779                ]
 9780            );
 9781            assert!(editor.selections.pending_anchor().is_some());
 9782        });
 9783    }
 9784
 9785    #[gpui::test]
 9786    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9787        cx.set_global(Settings::test(cx));
 9788        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9789        let mut excerpt1_id = None;
 9790        let multibuffer = cx.add_model(|cx| {
 9791            let mut multibuffer = MultiBuffer::new(0);
 9792            excerpt1_id = multibuffer
 9793                .push_excerpts(
 9794                    buffer.clone(),
 9795                    [
 9796                        ExcerptRange {
 9797                            context: Point::new(0, 0)..Point::new(1, 4),
 9798                            primary: None,
 9799                        },
 9800                        ExcerptRange {
 9801                            context: Point::new(1, 0)..Point::new(2, 4),
 9802                            primary: None,
 9803                        },
 9804                    ],
 9805                    cx,
 9806                )
 9807                .into_iter()
 9808                .next();
 9809            multibuffer
 9810        });
 9811        assert_eq!(
 9812            multibuffer.read(cx).read(cx).text(),
 9813            "aaaa\nbbbb\nbbbb\ncccc"
 9814        );
 9815        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9816            let mut editor = build_editor(multibuffer.clone(), cx);
 9817            let snapshot = editor.snapshot(cx);
 9818            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9819            assert_eq!(
 9820                editor.selections.ranges(cx),
 9821                [Point::new(1, 3)..Point::new(1, 3)]
 9822            );
 9823            editor
 9824        });
 9825
 9826        multibuffer.update(cx, |multibuffer, cx| {
 9827            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9828        });
 9829        editor.update(cx, |editor, cx| {
 9830            assert_eq!(
 9831                editor.selections.ranges(cx),
 9832                [Point::new(0, 0)..Point::new(0, 0)]
 9833            );
 9834
 9835            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9836            editor.change_selections(None, cx, |s| {
 9837                s.refresh();
 9838            });
 9839            assert_eq!(
 9840                editor.selections.ranges(cx),
 9841                [Point::new(0, 3)..Point::new(0, 3)]
 9842            );
 9843            assert!(editor.selections.pending_anchor().is_some());
 9844        });
 9845    }
 9846
 9847    #[gpui::test]
 9848    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
 9849        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9850        let language = Arc::new(Language::new(
 9851            LanguageConfig {
 9852                brackets: vec![
 9853                    BracketPair {
 9854                        start: "{".to_string(),
 9855                        end: "}".to_string(),
 9856                        close: true,
 9857                        newline: true,
 9858                    },
 9859                    BracketPair {
 9860                        start: "/* ".to_string(),
 9861                        end: " */".to_string(),
 9862                        close: true,
 9863                        newline: true,
 9864                    },
 9865                ],
 9866                ..Default::default()
 9867            },
 9868            Some(tree_sitter_rust::language()),
 9869        ));
 9870
 9871        let text = concat!(
 9872            "{   }\n",     // Suppress rustfmt
 9873            "  x\n",       //
 9874            "  /*   */\n", //
 9875            "x\n",         //
 9876            "{{} }\n",     //
 9877        );
 9878
 9879        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9880        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9881        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9882        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9883            .await;
 9884
 9885        view.update(cx, |view, cx| {
 9886            view.change_selections(None, cx, |s| {
 9887                s.select_display_ranges([
 9888                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 9889                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9890                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9891                ])
 9892            });
 9893            view.newline(&Newline, cx);
 9894
 9895            assert_eq!(
 9896                view.buffer().read(cx).read(cx).text(),
 9897                concat!(
 9898                    "{ \n",    // Suppress rustfmt
 9899                    "\n",      //
 9900                    "}\n",     //
 9901                    "  x\n",   //
 9902                    "  /* \n", //
 9903                    "  \n",    //
 9904                    "  */\n",  //
 9905                    "x\n",     //
 9906                    "{{} \n",  //
 9907                    "}\n",     //
 9908                )
 9909            );
 9910        });
 9911    }
 9912
 9913    #[gpui::test]
 9914    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
 9915        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9916
 9917        cx.set_global(Settings::test(cx));
 9918        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9919
 9920        editor.update(cx, |editor, cx| {
 9921            struct Type1;
 9922            struct Type2;
 9923
 9924            let buffer = buffer.read(cx).snapshot(cx);
 9925
 9926            let anchor_range = |range: Range<Point>| {
 9927                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
 9928            };
 9929
 9930            editor.highlight_background::<Type1>(
 9931                vec![
 9932                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
 9933                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
 9934                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
 9935                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
 9936                ],
 9937                |_| Color::red(),
 9938                cx,
 9939            );
 9940            editor.highlight_background::<Type2>(
 9941                vec![
 9942                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
 9943                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
 9944                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
 9945                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
 9946                ],
 9947                |_| Color::green(),
 9948                cx,
 9949            );
 9950
 9951            let snapshot = editor.snapshot(cx);
 9952            let mut highlighted_ranges = editor.background_highlights_in_range(
 9953                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
 9954                &snapshot,
 9955                cx.global::<Settings>().theme.as_ref(),
 9956            );
 9957            // Enforce a consistent ordering based on color without relying on the ordering of the
 9958            // highlight's `TypeId` which is non-deterministic.
 9959            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
 9960            assert_eq!(
 9961                highlighted_ranges,
 9962                &[
 9963                    (
 9964                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
 9965                        Color::green(),
 9966                    ),
 9967                    (
 9968                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
 9969                        Color::green(),
 9970                    ),
 9971                    (
 9972                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
 9973                        Color::red(),
 9974                    ),
 9975                    (
 9976                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9977                        Color::red(),
 9978                    ),
 9979                ]
 9980            );
 9981            assert_eq!(
 9982                editor.background_highlights_in_range(
 9983                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
 9984                    &snapshot,
 9985                    cx.global::<Settings>().theme.as_ref(),
 9986                ),
 9987                &[(
 9988                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9989                    Color::red(),
 9990                )]
 9991            );
 9992        });
 9993    }
 9994
 9995    #[gpui::test]
 9996    fn test_following(cx: &mut gpui::MutableAppContext) {
 9997        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9998
 9999        cx.set_global(Settings::test(cx));
10000
10001        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10002        let (_, follower) = cx.add_window(
10003            WindowOptions {
10004                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10005                ..Default::default()
10006            },
10007            |cx| build_editor(buffer.clone(), cx),
10008        );
10009
10010        let pending_update = Rc::new(RefCell::new(None));
10011        follower.update(cx, {
10012            let update = pending_update.clone();
10013            |_, cx| {
10014                cx.subscribe(&leader, move |_, leader, event, cx| {
10015                    leader
10016                        .read(cx)
10017                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10018                })
10019                .detach();
10020            }
10021        });
10022
10023        // Update the selections only
10024        leader.update(cx, |leader, cx| {
10025            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10026        });
10027        follower.update(cx, |follower, cx| {
10028            follower
10029                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10030                .unwrap();
10031        });
10032        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
10033
10034        // Update the scroll position only
10035        leader.update(cx, |leader, cx| {
10036            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10037        });
10038        follower.update(cx, |follower, cx| {
10039            follower
10040                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10041                .unwrap();
10042        });
10043        assert_eq!(
10044            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10045            vec2f(1.5, 3.5)
10046        );
10047
10048        // Update the selections and scroll position
10049        leader.update(cx, |leader, cx| {
10050            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
10051            leader.request_autoscroll(Autoscroll::Newest, cx);
10052            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10053        });
10054        follower.update(cx, |follower, cx| {
10055            let initial_scroll_position = follower.scroll_position(cx);
10056            follower
10057                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10058                .unwrap();
10059            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10060            assert!(follower.autoscroll_request.is_some());
10061        });
10062        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
10063
10064        // Creating a pending selection that precedes another selection
10065        leader.update(cx, |leader, cx| {
10066            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10067            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10068        });
10069        follower.update(cx, |follower, cx| {
10070            follower
10071                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10072                .unwrap();
10073        });
10074        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
10075
10076        // Extend the pending selection so that it surrounds another selection
10077        leader.update(cx, |leader, cx| {
10078            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10079        });
10080        follower.update(cx, |follower, cx| {
10081            follower
10082                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10083                .unwrap();
10084        });
10085        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
10086    }
10087
10088    #[test]
10089    fn test_combine_syntax_and_fuzzy_match_highlights() {
10090        let string = "abcdefghijklmnop";
10091        let syntax_ranges = [
10092            (
10093                0..3,
10094                HighlightStyle {
10095                    color: Some(Color::red()),
10096                    ..Default::default()
10097                },
10098            ),
10099            (
10100                4..8,
10101                HighlightStyle {
10102                    color: Some(Color::green()),
10103                    ..Default::default()
10104                },
10105            ),
10106        ];
10107        let match_indices = [4, 6, 7, 8];
10108        assert_eq!(
10109            combine_syntax_and_fuzzy_match_highlights(
10110                &string,
10111                Default::default(),
10112                syntax_ranges.into_iter(),
10113                &match_indices,
10114            ),
10115            &[
10116                (
10117                    0..3,
10118                    HighlightStyle {
10119                        color: Some(Color::red()),
10120                        ..Default::default()
10121                    },
10122                ),
10123                (
10124                    4..5,
10125                    HighlightStyle {
10126                        color: Some(Color::green()),
10127                        weight: Some(fonts::Weight::BOLD),
10128                        ..Default::default()
10129                    },
10130                ),
10131                (
10132                    5..6,
10133                    HighlightStyle {
10134                        color: Some(Color::green()),
10135                        ..Default::default()
10136                    },
10137                ),
10138                (
10139                    6..8,
10140                    HighlightStyle {
10141                        color: Some(Color::green()),
10142                        weight: Some(fonts::Weight::BOLD),
10143                        ..Default::default()
10144                    },
10145                ),
10146                (
10147                    8..9,
10148                    HighlightStyle {
10149                        weight: Some(fonts::Weight::BOLD),
10150                        ..Default::default()
10151                    },
10152                ),
10153            ]
10154        );
10155    }
10156
10157    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10158        let point = DisplayPoint::new(row as u32, column as u32);
10159        point..point
10160    }
10161
10162    fn assert_selection_ranges(
10163        marked_text: &str,
10164        selection_marker_pairs: Vec<(char, char)>,
10165        view: &mut Editor,
10166        cx: &mut ViewContext<Editor>,
10167    ) {
10168        let snapshot = view.snapshot(cx).display_snapshot;
10169        let mut marker_chars = Vec::new();
10170        for (start, end) in selection_marker_pairs.iter() {
10171            marker_chars.push(*start);
10172            marker_chars.push(*end);
10173        }
10174        let (_, markers) = marked_text_by(marked_text, marker_chars);
10175        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10176            .iter()
10177            .map(|(start, end)| {
10178                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10179                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10180                start..end
10181            })
10182            .collect();
10183        assert_eq!(
10184            view.selections.display_ranges(cx),
10185            &asserted_ranges[..],
10186            "Assert selections are {}",
10187            marked_text
10188        );
10189    }
10190}
10191
10192trait RangeExt<T> {
10193    fn sorted(&self) -> Range<T>;
10194    fn to_inclusive(&self) -> RangeInclusive<T>;
10195}
10196
10197impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10198    fn sorted(&self) -> Self {
10199        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10200    }
10201
10202    fn to_inclusive(&self) -> RangeInclusive<T> {
10203        self.start.clone()..=self.end.clone()
10204    }
10205}