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