editor.rs

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