editor.rs

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