editor.rs

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