editor.rs

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