editor.rs

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