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        goal_column: u32,
  343    },
  344    Extend {
  345        position: DisplayPoint,
  346        click_count: usize,
  347    },
  348    Update {
  349        position: DisplayPoint,
  350        goal_column: 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                goal_column,
 1504            } => self.begin_columnar_selection(*position, *goal_column, cx),
 1505            SelectPhase::Extend {
 1506                position,
 1507                click_count,
 1508            } => self.extend_selection(*position, *click_count, cx),
 1509            SelectPhase::Update {
 1510                position,
 1511                goal_column,
 1512                scroll_position,
 1513            } => self.update_selection(*position, *goal_column, *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        goal_column: 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            goal_column,
 1637            &display_map,
 1638            cx,
 1639        );
 1640    }
 1641
 1642    fn update_selection(
 1643        &mut self,
 1644        position: DisplayPoint,
 1645        goal_column: 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, goal_column, &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        goal_column: 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(), goal_column);
 1761        let end_column = cmp::max(tail.column(), goal_column);
 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 the selection is non-empty, then increase the indentation of the selected lines.
 2983            if !selection.is_empty() {
 2984                row_delta =
 2985                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 2986                continue;
 2987            }
 2988
 2989            // If the selection is empty and the cursor is in the leading whitespace before the
 2990            // suggested indentation, then auto-indent the line.
 2991            let cursor = selection.head();
 2992            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
 2993                let current_indent = snapshot.indent_size_for_line(cursor.row);
 2994                if cursor.column < suggested_indent.len
 2995                    && cursor.column <= current_indent.len
 2996                    && current_indent.len <= suggested_indent.len
 2997                {
 2998                    selection.start = Point::new(cursor.row, suggested_indent.len);
 2999                    selection.end = selection.start;
 3000                    if row_delta == 0 {
 3001                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 3002                            cursor.row,
 3003                            current_indent,
 3004                            suggested_indent,
 3005                        ));
 3006                        row_delta = suggested_indent.len - current_indent.len;
 3007                    }
 3008                    continue;
 3009                }
 3010            }
 3011
 3012            // Otherwise, insert a hard or soft tab.
 3013            let settings = cx.global::<Settings>();
 3014            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
 3015            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
 3016                IndentSize::tab()
 3017            } else {
 3018                let tab_size = settings.tab_size(language_name.as_deref()).get();
 3019                let char_column = snapshot
 3020                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 3021                    .flat_map(str::chars)
 3022                    .count()
 3023                    + row_delta as usize;
 3024                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 3025                IndentSize::spaces(chars_to_next_tab_stop)
 3026            };
 3027            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 3028            selection.end = selection.start;
 3029            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 3030            row_delta += tab_size.len;
 3031        }
 3032
 3033        self.transact(cx, |this, cx| {
 3034            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 3035            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections))
 3036        });
 3037    }
 3038
 3039    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 3040        let mut selections = self.selections.all::<Point>(cx);
 3041        let mut prev_edited_row = 0;
 3042        let mut row_delta = 0;
 3043        let mut edits = Vec::new();
 3044        let buffer = self.buffer.read(cx);
 3045        let snapshot = buffer.snapshot(cx);
 3046        for selection in &mut selections {
 3047            if selection.start.row != prev_edited_row {
 3048                row_delta = 0;
 3049            }
 3050            prev_edited_row = selection.end.row;
 3051
 3052            row_delta =
 3053                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 3054        }
 3055
 3056        self.transact(cx, |this, cx| {
 3057            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 3058            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 3059        });
 3060    }
 3061
 3062    fn indent_selection(
 3063        buffer: &MultiBuffer,
 3064        snapshot: &MultiBufferSnapshot,
 3065        selection: &mut Selection<Point>,
 3066        edits: &mut Vec<(Range<Point>, String)>,
 3067        delta_for_start_row: u32,
 3068        cx: &AppContext,
 3069    ) -> u32 {
 3070        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
 3071        let settings = cx.global::<Settings>();
 3072        let tab_size = settings.tab_size(language_name.as_deref()).get();
 3073        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
 3074            IndentKind::Tab
 3075        } else {
 3076            IndentKind::Space
 3077        };
 3078        let mut start_row = selection.start.row;
 3079        let mut end_row = selection.end.row + 1;
 3080
 3081        // If a selection ends at the beginning of a line, don't indent
 3082        // that last line.
 3083        if selection.end.column == 0 {
 3084            end_row -= 1;
 3085        }
 3086
 3087        // Avoid re-indenting a row that has already been indented by a
 3088        // previous selection, but still update this selection's column
 3089        // to reflect that indentation.
 3090        if delta_for_start_row > 0 {
 3091            start_row += 1;
 3092            selection.start.column += delta_for_start_row;
 3093            if selection.end.row == selection.start.row {
 3094                selection.end.column += delta_for_start_row;
 3095            }
 3096        }
 3097
 3098        let mut delta_for_end_row = 0;
 3099        for row in start_row..end_row {
 3100            let current_indent = snapshot.indent_size_for_line(row);
 3101            let indent_delta = match (current_indent.kind, indent_kind) {
 3102                (IndentKind::Space, IndentKind::Space) => {
 3103                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 3104                    IndentSize::spaces(columns_to_next_tab_stop)
 3105                }
 3106                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 3107                (_, IndentKind::Tab) => IndentSize::tab(),
 3108            };
 3109
 3110            let row_start = Point::new(row, 0);
 3111            edits.push((
 3112                row_start..row_start,
 3113                indent_delta.chars().collect::<String>(),
 3114            ));
 3115
 3116            // Update this selection's endpoints to reflect the indentation.
 3117            if row == selection.start.row {
 3118                selection.start.column += indent_delta.len;
 3119            }
 3120            if row == selection.end.row {
 3121                selection.end.column += indent_delta.len;
 3122                delta_for_end_row = indent_delta.len;
 3123            }
 3124        }
 3125
 3126        if selection.start.row == selection.end.row {
 3127            delta_for_start_row + delta_for_end_row
 3128        } else {
 3129            delta_for_end_row
 3130        }
 3131    }
 3132
 3133    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 3134        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3135        let selections = self.selections.all::<Point>(cx);
 3136        let mut deletion_ranges = Vec::new();
 3137        let mut last_outdent = None;
 3138        {
 3139            let buffer = self.buffer.read(cx);
 3140            let snapshot = buffer.snapshot(cx);
 3141            for selection in &selections {
 3142                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
 3143                let tab_size = cx
 3144                    .global::<Settings>()
 3145                    .tab_size(language_name.as_deref())
 3146                    .get();
 3147                let mut rows = selection.spanned_rows(false, &display_map);
 3148
 3149                // Avoid re-outdenting a row that has already been outdented by a
 3150                // previous selection.
 3151                if let Some(last_row) = last_outdent {
 3152                    if last_row == rows.start {
 3153                        rows.start += 1;
 3154                    }
 3155                }
 3156
 3157                for row in rows {
 3158                    let indent_size = snapshot.indent_size_for_line(row);
 3159                    if indent_size.len > 0 {
 3160                        let deletion_len = match indent_size.kind {
 3161                            IndentKind::Space => {
 3162                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 3163                                if columns_to_prev_tab_stop == 0 {
 3164                                    tab_size
 3165                                } else {
 3166                                    columns_to_prev_tab_stop
 3167                                }
 3168                            }
 3169                            IndentKind::Tab => 1,
 3170                        };
 3171                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 3172                        last_outdent = Some(row);
 3173                    }
 3174                }
 3175            }
 3176        }
 3177
 3178        self.transact(cx, |this, cx| {
 3179            this.buffer.update(cx, |buffer, cx| {
 3180                let empty_str: Arc<str> = "".into();
 3181                buffer.edit(
 3182                    deletion_ranges
 3183                        .into_iter()
 3184                        .map(|range| (range, empty_str.clone())),
 3185                    None,
 3186                    cx,
 3187                );
 3188            });
 3189            let selections = this.selections.all::<usize>(cx);
 3190            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 3191        });
 3192    }
 3193
 3194    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 3195        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3196        let selections = self.selections.all::<Point>(cx);
 3197
 3198        let mut new_cursors = Vec::new();
 3199        let mut edit_ranges = Vec::new();
 3200        let mut selections = selections.iter().peekable();
 3201        while let Some(selection) = selections.next() {
 3202            let mut rows = selection.spanned_rows(false, &display_map);
 3203            let goal_display_column = selection.head().to_display_point(&display_map).column();
 3204
 3205            // Accumulate contiguous regions of rows that we want to delete.
 3206            while let Some(next_selection) = selections.peek() {
 3207                let next_rows = next_selection.spanned_rows(false, &display_map);
 3208                if next_rows.start <= rows.end {
 3209                    rows.end = next_rows.end;
 3210                    selections.next().unwrap();
 3211                } else {
 3212                    break;
 3213                }
 3214            }
 3215
 3216            let buffer = &display_map.buffer_snapshot;
 3217            let mut edit_start = Point::new(rows.start, 0).to_offset(&buffer);
 3218            let edit_end;
 3219            let cursor_buffer_row;
 3220            if buffer.max_point().row >= rows.end {
 3221                // If there's a line after the range, delete the \n from the end of the row range
 3222                // and position the cursor on the next line.
 3223                edit_end = Point::new(rows.end, 0).to_offset(&buffer);
 3224                cursor_buffer_row = rows.end;
 3225            } else {
 3226                // If there isn't a line after the range, delete the \n from the line before the
 3227                // start of the row range and position the cursor there.
 3228                edit_start = edit_start.saturating_sub(1);
 3229                edit_end = buffer.len();
 3230                cursor_buffer_row = rows.start.saturating_sub(1);
 3231            }
 3232
 3233            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 3234            *cursor.column_mut() =
 3235                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 3236
 3237            new_cursors.push((
 3238                selection.id,
 3239                buffer.anchor_after(cursor.to_point(&display_map)),
 3240            ));
 3241            edit_ranges.push(edit_start..edit_end);
 3242        }
 3243
 3244        self.transact(cx, |this, cx| {
 3245            let buffer = this.buffer.update(cx, |buffer, cx| {
 3246                let empty_str: Arc<str> = "".into();
 3247                buffer.edit(
 3248                    edit_ranges
 3249                        .into_iter()
 3250                        .map(|range| (range, empty_str.clone())),
 3251                    None,
 3252                    cx,
 3253                );
 3254                buffer.snapshot(cx)
 3255            });
 3256            let new_selections = new_cursors
 3257                .into_iter()
 3258                .map(|(id, cursor)| {
 3259                    let cursor = cursor.to_point(&buffer);
 3260                    Selection {
 3261                        id,
 3262                        start: cursor,
 3263                        end: cursor,
 3264                        reversed: false,
 3265                        goal: SelectionGoal::None,
 3266                    }
 3267                })
 3268                .collect();
 3269
 3270            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3271                s.select(new_selections);
 3272            });
 3273        });
 3274    }
 3275
 3276    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 3277        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3278        let buffer = &display_map.buffer_snapshot;
 3279        let selections = self.selections.all::<Point>(cx);
 3280
 3281        let mut edits = Vec::new();
 3282        let mut selections_iter = selections.iter().peekable();
 3283        while let Some(selection) = selections_iter.next() {
 3284            // Avoid duplicating the same lines twice.
 3285            let mut rows = selection.spanned_rows(false, &display_map);
 3286
 3287            while let Some(next_selection) = selections_iter.peek() {
 3288                let next_rows = next_selection.spanned_rows(false, &display_map);
 3289                if next_rows.start <= rows.end - 1 {
 3290                    rows.end = next_rows.end;
 3291                    selections_iter.next().unwrap();
 3292                } else {
 3293                    break;
 3294                }
 3295            }
 3296
 3297            // Copy the text from the selected row region and splice it at the start of the region.
 3298            let start = Point::new(rows.start, 0);
 3299            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 3300            let text = buffer
 3301                .text_for_range(start..end)
 3302                .chain(Some("\n"))
 3303                .collect::<String>();
 3304            edits.push((start..start, text));
 3305        }
 3306
 3307        self.transact(cx, |this, cx| {
 3308            this.buffer.update(cx, |buffer, cx| {
 3309                buffer.edit(edits, None, cx);
 3310            });
 3311
 3312            this.request_autoscroll(Autoscroll::Fit, cx);
 3313        });
 3314    }
 3315
 3316    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 3317        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3318        let buffer = self.buffer.read(cx).snapshot(cx);
 3319
 3320        let mut edits = Vec::new();
 3321        let mut unfold_ranges = Vec::new();
 3322        let mut refold_ranges = Vec::new();
 3323
 3324        let selections = self.selections.all::<Point>(cx);
 3325        let mut selections = selections.iter().peekable();
 3326        let mut contiguous_row_selections = Vec::new();
 3327        let mut new_selections = Vec::new();
 3328
 3329        while let Some(selection) = selections.next() {
 3330            // Find all the selections that span a contiguous row range
 3331            contiguous_row_selections.push(selection.clone());
 3332            let start_row = selection.start.row;
 3333            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
 3334                display_map.next_line_boundary(selection.end).0.row + 1
 3335            } else {
 3336                selection.end.row
 3337            };
 3338
 3339            while let Some(next_selection) = selections.peek() {
 3340                if next_selection.start.row <= end_row {
 3341                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
 3342                        display_map.next_line_boundary(next_selection.end).0.row + 1
 3343                    } else {
 3344                        next_selection.end.row
 3345                    };
 3346                    contiguous_row_selections.push(selections.next().unwrap().clone());
 3347                } else {
 3348                    break;
 3349                }
 3350            }
 3351
 3352            // Move the text spanned by the row range to be before the line preceding the row range
 3353            if start_row > 0 {
 3354                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 3355                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 3356                let insertion_point = display_map
 3357                    .prev_line_boundary(Point::new(start_row - 1, 0))
 3358                    .0;
 3359
 3360                // Don't move lines across excerpts
 3361                if buffer
 3362                    .excerpt_boundaries_in_range((
 3363                        Bound::Excluded(insertion_point),
 3364                        Bound::Included(range_to_move.end),
 3365                    ))
 3366                    .next()
 3367                    .is_none()
 3368                {
 3369                    let text = buffer
 3370                        .text_for_range(range_to_move.clone())
 3371                        .flat_map(|s| s.chars())
 3372                        .skip(1)
 3373                        .chain(['\n'])
 3374                        .collect::<String>();
 3375
 3376                    edits.push((
 3377                        buffer.anchor_after(range_to_move.start)
 3378                            ..buffer.anchor_before(range_to_move.end),
 3379                        String::new(),
 3380                    ));
 3381                    let insertion_anchor = buffer.anchor_after(insertion_point);
 3382                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
 3383
 3384                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 3385
 3386                    // Move selections up
 3387                    new_selections.extend(contiguous_row_selections.drain(..).map(
 3388                        |mut selection| {
 3389                            selection.start.row -= row_delta;
 3390                            selection.end.row -= row_delta;
 3391                            selection
 3392                        },
 3393                    ));
 3394
 3395                    // Move folds up
 3396                    unfold_ranges.push(range_to_move.clone());
 3397                    for fold in display_map.folds_in_range(
 3398                        buffer.anchor_before(range_to_move.start)
 3399                            ..buffer.anchor_after(range_to_move.end),
 3400                    ) {
 3401                        let mut start = fold.start.to_point(&buffer);
 3402                        let mut end = fold.end.to_point(&buffer);
 3403                        start.row -= row_delta;
 3404                        end.row -= row_delta;
 3405                        refold_ranges.push(start..end);
 3406                    }
 3407                }
 3408            }
 3409
 3410            // If we didn't move line(s), preserve the existing selections
 3411            new_selections.extend(contiguous_row_selections.drain(..));
 3412        }
 3413
 3414        self.transact(cx, |this, cx| {
 3415            this.unfold_ranges(unfold_ranges, true, cx);
 3416            this.buffer.update(cx, |buffer, cx| {
 3417                for (range, text) in edits {
 3418                    buffer.edit([(range, text)], None, cx);
 3419                }
 3420            });
 3421            this.fold_ranges(refold_ranges, cx);
 3422            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3423                s.select(new_selections);
 3424            })
 3425        });
 3426    }
 3427
 3428    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 3429        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3430        let buffer = self.buffer.read(cx).snapshot(cx);
 3431
 3432        let mut edits = Vec::new();
 3433        let mut unfold_ranges = Vec::new();
 3434        let mut refold_ranges = Vec::new();
 3435
 3436        let selections = self.selections.all::<Point>(cx);
 3437        let mut selections = selections.iter().peekable();
 3438        let mut contiguous_row_selections = Vec::new();
 3439        let mut new_selections = Vec::new();
 3440
 3441        while let Some(selection) = selections.next() {
 3442            // Find all the selections that span a contiguous row range
 3443            contiguous_row_selections.push(selection.clone());
 3444            let start_row = selection.start.row;
 3445            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
 3446                display_map.next_line_boundary(selection.end).0.row + 1
 3447            } else {
 3448                selection.end.row
 3449            };
 3450
 3451            while let Some(next_selection) = selections.peek() {
 3452                if next_selection.start.row <= end_row {
 3453                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
 3454                        display_map.next_line_boundary(next_selection.end).0.row + 1
 3455                    } else {
 3456                        next_selection.end.row
 3457                    };
 3458                    contiguous_row_selections.push(selections.next().unwrap().clone());
 3459                } else {
 3460                    break;
 3461                }
 3462            }
 3463
 3464            // Move the text spanned by the row range to be after the last line of the row range
 3465            if end_row <= buffer.max_point().row {
 3466                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 3467                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 3468
 3469                // Don't move lines across excerpt boundaries
 3470                if buffer
 3471                    .excerpt_boundaries_in_range((
 3472                        Bound::Excluded(range_to_move.start),
 3473                        Bound::Included(insertion_point),
 3474                    ))
 3475                    .next()
 3476                    .is_none()
 3477                {
 3478                    let mut text = String::from("\n");
 3479                    text.extend(buffer.text_for_range(range_to_move.clone()));
 3480                    text.pop(); // Drop trailing newline
 3481                    edits.push((
 3482                        buffer.anchor_after(range_to_move.start)
 3483                            ..buffer.anchor_before(range_to_move.end),
 3484                        String::new(),
 3485                    ));
 3486                    let insertion_anchor = buffer.anchor_after(insertion_point);
 3487                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
 3488
 3489                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 3490
 3491                    // Move selections down
 3492                    new_selections.extend(contiguous_row_selections.drain(..).map(
 3493                        |mut selection| {
 3494                            selection.start.row += row_delta;
 3495                            selection.end.row += row_delta;
 3496                            selection
 3497                        },
 3498                    ));
 3499
 3500                    // Move folds down
 3501                    unfold_ranges.push(range_to_move.clone());
 3502                    for fold in display_map.folds_in_range(
 3503                        buffer.anchor_before(range_to_move.start)
 3504                            ..buffer.anchor_after(range_to_move.end),
 3505                    ) {
 3506                        let mut start = fold.start.to_point(&buffer);
 3507                        let mut end = fold.end.to_point(&buffer);
 3508                        start.row += row_delta;
 3509                        end.row += row_delta;
 3510                        refold_ranges.push(start..end);
 3511                    }
 3512                }
 3513            }
 3514
 3515            // If we didn't move line(s), preserve the existing selections
 3516            new_selections.extend(contiguous_row_selections.drain(..));
 3517        }
 3518
 3519        self.transact(cx, |this, cx| {
 3520            this.unfold_ranges(unfold_ranges, true, cx);
 3521            this.buffer.update(cx, |buffer, cx| {
 3522                for (range, text) in edits {
 3523                    buffer.edit([(range, text)], None, cx);
 3524                }
 3525            });
 3526            this.fold_ranges(refold_ranges, cx);
 3527            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
 3528        });
 3529    }
 3530
 3531    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 3532        self.transact(cx, |this, cx| {
 3533            let edits = this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3534                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 3535                let line_mode = s.line_mode;
 3536                s.move_with(|display_map, selection| {
 3537                    if !selection.is_empty() || line_mode {
 3538                        return;
 3539                    }
 3540
 3541                    let mut head = selection.head();
 3542                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 3543                    if head.column() == display_map.line_len(head.row()) {
 3544                        transpose_offset = display_map
 3545                            .buffer_snapshot
 3546                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3547                    }
 3548
 3549                    if transpose_offset == 0 {
 3550                        return;
 3551                    }
 3552
 3553                    *head.column_mut() += 1;
 3554                    head = display_map.clip_point(head, Bias::Right);
 3555                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
 3556
 3557                    let transpose_start = display_map
 3558                        .buffer_snapshot
 3559                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3560                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 3561                        let transpose_end = display_map
 3562                            .buffer_snapshot
 3563                            .clip_offset(transpose_offset + 1, Bias::Right);
 3564                        if let Some(ch) =
 3565                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 3566                        {
 3567                            edits.push((transpose_start..transpose_offset, String::new()));
 3568                            edits.push((transpose_end..transpose_end, ch.to_string()));
 3569                        }
 3570                    }
 3571                });
 3572                edits
 3573            });
 3574            this.buffer
 3575                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 3576            let selections = this.selections.all::<usize>(cx);
 3577            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3578                s.select(selections);
 3579            });
 3580        });
 3581    }
 3582
 3583    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 3584        let mut text = String::new();
 3585        let buffer = self.buffer.read(cx).snapshot(cx);
 3586        let mut selections = self.selections.all::<Point>(cx);
 3587        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3588        {
 3589            let max_point = buffer.max_point();
 3590            for selection in &mut selections {
 3591                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 3592                if is_entire_line {
 3593                    selection.start = Point::new(selection.start.row, 0);
 3594                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 3595                    selection.goal = SelectionGoal::None;
 3596                }
 3597                let mut len = 0;
 3598                for chunk in buffer.text_for_range(selection.start..selection.end) {
 3599                    text.push_str(chunk);
 3600                    len += chunk.len();
 3601                }
 3602                clipboard_selections.push(ClipboardSelection {
 3603                    len,
 3604                    is_entire_line,
 3605                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
 3606                });
 3607            }
 3608        }
 3609
 3610        self.transact(cx, |this, cx| {
 3611            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3612                s.select(selections);
 3613            });
 3614            this.insert("", cx);
 3615            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3616        });
 3617    }
 3618
 3619    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 3620        let selections = self.selections.all::<Point>(cx);
 3621        let buffer = self.buffer.read(cx).read(cx);
 3622        let mut text = String::new();
 3623
 3624        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3625        {
 3626            let max_point = buffer.max_point();
 3627            for selection in selections.iter() {
 3628                let mut start = selection.start;
 3629                let mut end = selection.end;
 3630                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 3631                if is_entire_line {
 3632                    start = Point::new(start.row, 0);
 3633                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 3634                }
 3635                let mut len = 0;
 3636                for chunk in buffer.text_for_range(start..end) {
 3637                    text.push_str(chunk);
 3638                    len += chunk.len();
 3639                }
 3640                clipboard_selections.push(ClipboardSelection {
 3641                    len,
 3642                    is_entire_line,
 3643                    first_line_indent: buffer.indent_size_for_line(start.row).len,
 3644                });
 3645            }
 3646        }
 3647
 3648        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3649    }
 3650
 3651    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 3652        self.transact(cx, |this, cx| {
 3653            if let Some(item) = cx.as_mut().read_from_clipboard() {
 3654                let mut clipboard_text = Cow::Borrowed(item.text());
 3655                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 3656                    let old_selections = this.selections.all::<usize>(cx);
 3657                    let all_selections_were_entire_line =
 3658                        clipboard_selections.iter().all(|s| s.is_entire_line);
 3659                    let first_selection_indent_column =
 3660                        clipboard_selections.first().map(|s| s.first_line_indent);
 3661                    if clipboard_selections.len() != old_selections.len() {
 3662                        let mut newline_separated_text = String::new();
 3663                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
 3664                        let mut ix = 0;
 3665                        while let Some(clipboard_selection) = clipboard_selections.next() {
 3666                            newline_separated_text
 3667                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
 3668                            ix += clipboard_selection.len;
 3669                            if clipboard_selections.peek().is_some() {
 3670                                newline_separated_text.push('\n');
 3671                            }
 3672                        }
 3673                        clipboard_text = Cow::Owned(newline_separated_text);
 3674                    }
 3675
 3676                    this.buffer.update(cx, |buffer, cx| {
 3677                        let snapshot = buffer.read(cx);
 3678                        let mut start_offset = 0;
 3679                        let mut edits = Vec::new();
 3680                        let mut original_indent_columns = Vec::new();
 3681                        let line_mode = this.selections.line_mode;
 3682                        for (ix, selection) in old_selections.iter().enumerate() {
 3683                            let to_insert;
 3684                            let entire_line;
 3685                            let original_indent_column;
 3686                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 3687                                let end_offset = start_offset + clipboard_selection.len;
 3688                                to_insert = &clipboard_text[start_offset..end_offset];
 3689                                entire_line = clipboard_selection.is_entire_line;
 3690                                start_offset = end_offset;
 3691                                original_indent_column =
 3692                                    Some(clipboard_selection.first_line_indent);
 3693                            } else {
 3694                                to_insert = clipboard_text.as_str();
 3695                                entire_line = all_selections_were_entire_line;
 3696                                original_indent_column = first_selection_indent_column
 3697                            }
 3698
 3699                            // If the corresponding selection was empty when this slice of the
 3700                            // clipboard text was written, then the entire line containing the
 3701                            // selection was copied. If this selection is also currently empty,
 3702                            // then paste the line before the current line of the buffer.
 3703                            let range = if selection.is_empty() && !line_mode && entire_line {
 3704                                let column = selection.start.to_point(&snapshot).column as usize;
 3705                                let line_start = selection.start - column;
 3706                                line_start..line_start
 3707                            } else {
 3708                                selection.range()
 3709                            };
 3710
 3711                            edits.push((range, to_insert));
 3712                            original_indent_columns.extend(original_indent_column);
 3713                        }
 3714                        drop(snapshot);
 3715
 3716                        buffer.edit(
 3717                            edits,
 3718                            Some(AutoindentMode::Block {
 3719                                original_indent_columns,
 3720                            }),
 3721                            cx,
 3722                        );
 3723                    });
 3724
 3725                    let selections = this.selections.all::<usize>(cx);
 3726                    this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 3727                } else {
 3728                    this.insert(&clipboard_text, cx);
 3729                }
 3730            }
 3731        });
 3732    }
 3733
 3734    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 3735        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 3736            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 3737                self.change_selections(None, cx, |s| {
 3738                    s.select_anchors(selections.to_vec());
 3739                });
 3740            }
 3741            self.request_autoscroll(Autoscroll::Fit, cx);
 3742            self.unmark_text(cx);
 3743            cx.emit(Event::Edited);
 3744        }
 3745    }
 3746
 3747    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 3748        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 3749            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 3750            {
 3751                self.change_selections(None, cx, |s| {
 3752                    s.select_anchors(selections.to_vec());
 3753                });
 3754            }
 3755            self.request_autoscroll(Autoscroll::Fit, cx);
 3756            self.unmark_text(cx);
 3757            cx.emit(Event::Edited);
 3758        }
 3759    }
 3760
 3761    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 3762        self.buffer
 3763            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 3764    }
 3765
 3766    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 3767        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3768            let line_mode = s.line_mode;
 3769            s.move_with(|map, selection| {
 3770                let cursor = if selection.is_empty() && !line_mode {
 3771                    movement::left(map, selection.start)
 3772                } else {
 3773                    selection.start
 3774                };
 3775                selection.collapse_to(cursor, SelectionGoal::None);
 3776            });
 3777        })
 3778    }
 3779
 3780    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 3781        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3782            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 3783        })
 3784    }
 3785
 3786    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 3787        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3788            let line_mode = s.line_mode;
 3789            s.move_with(|map, selection| {
 3790                let cursor = if selection.is_empty() && !line_mode {
 3791                    movement::right(map, selection.end)
 3792                } else {
 3793                    selection.end
 3794                };
 3795                selection.collapse_to(cursor, SelectionGoal::None)
 3796            });
 3797        })
 3798    }
 3799
 3800    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 3801        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3802            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 3803        })
 3804    }
 3805
 3806    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 3807        if self.take_rename(true, cx).is_some() {
 3808            return;
 3809        }
 3810
 3811        if let Some(context_menu) = self.context_menu.as_mut() {
 3812            if context_menu.select_prev(cx) {
 3813                return;
 3814            }
 3815        }
 3816
 3817        if matches!(self.mode, EditorMode::SingleLine) {
 3818            cx.propagate_action();
 3819            return;
 3820        }
 3821
 3822        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3823            let line_mode = s.line_mode;
 3824            s.move_with(|map, selection| {
 3825                if !selection.is_empty() && !line_mode {
 3826                    selection.goal = SelectionGoal::None;
 3827                }
 3828                let (cursor, goal) = movement::up(&map, selection.start, selection.goal, false);
 3829                selection.collapse_to(cursor, goal);
 3830            });
 3831        })
 3832    }
 3833
 3834    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 3835        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3836            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
 3837        })
 3838    }
 3839
 3840    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 3841        self.take_rename(true, cx);
 3842
 3843        if let Some(context_menu) = self.context_menu.as_mut() {
 3844            if context_menu.select_next(cx) {
 3845                return;
 3846            }
 3847        }
 3848
 3849        if matches!(self.mode, EditorMode::SingleLine) {
 3850            cx.propagate_action();
 3851            return;
 3852        }
 3853
 3854        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3855            let line_mode = s.line_mode;
 3856            s.move_with(|map, selection| {
 3857                if !selection.is_empty() && !line_mode {
 3858                    selection.goal = SelectionGoal::None;
 3859                }
 3860                let (cursor, goal) = movement::down(&map, selection.end, selection.goal, false);
 3861                selection.collapse_to(cursor, goal);
 3862            });
 3863        });
 3864    }
 3865
 3866    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 3867        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3868            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
 3869        });
 3870    }
 3871
 3872    pub fn move_to_previous_word_start(
 3873        &mut self,
 3874        _: &MoveToPreviousWordStart,
 3875        cx: &mut ViewContext<Self>,
 3876    ) {
 3877        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3878            s.move_cursors_with(|map, head, _| {
 3879                (
 3880                    movement::previous_word_start(map, head),
 3881                    SelectionGoal::None,
 3882                )
 3883            });
 3884        })
 3885    }
 3886
 3887    pub fn move_to_previous_subword_start(
 3888        &mut self,
 3889        _: &MoveToPreviousSubwordStart,
 3890        cx: &mut ViewContext<Self>,
 3891    ) {
 3892        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3893            s.move_cursors_with(|map, head, _| {
 3894                (
 3895                    movement::previous_subword_start(map, head),
 3896                    SelectionGoal::None,
 3897                )
 3898            });
 3899        })
 3900    }
 3901
 3902    pub fn select_to_previous_word_start(
 3903        &mut self,
 3904        _: &SelectToPreviousWordStart,
 3905        cx: &mut ViewContext<Self>,
 3906    ) {
 3907        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3908            s.move_heads_with(|map, head, _| {
 3909                (
 3910                    movement::previous_word_start(map, head),
 3911                    SelectionGoal::None,
 3912                )
 3913            });
 3914        })
 3915    }
 3916
 3917    pub fn select_to_previous_subword_start(
 3918        &mut self,
 3919        _: &SelectToPreviousSubwordStart,
 3920        cx: &mut ViewContext<Self>,
 3921    ) {
 3922        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3923            s.move_heads_with(|map, head, _| {
 3924                (
 3925                    movement::previous_subword_start(map, head),
 3926                    SelectionGoal::None,
 3927                )
 3928            });
 3929        })
 3930    }
 3931
 3932    pub fn delete_to_previous_word_start(
 3933        &mut self,
 3934        _: &DeleteToPreviousWordStart,
 3935        cx: &mut ViewContext<Self>,
 3936    ) {
 3937        self.transact(cx, |this, cx| {
 3938            if !this.select_autoclose_pair(cx) {
 3939                this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3940                    let line_mode = s.line_mode;
 3941                    s.move_with(|map, selection| {
 3942                        if selection.is_empty() && !line_mode {
 3943                            let cursor = movement::previous_word_start(map, selection.head());
 3944                            selection.set_head(cursor, SelectionGoal::None);
 3945                        }
 3946                    });
 3947                });
 3948            }
 3949            this.insert("", cx);
 3950        });
 3951    }
 3952
 3953    pub fn delete_to_previous_subword_start(
 3954        &mut self,
 3955        _: &DeleteToPreviousSubwordStart,
 3956        cx: &mut ViewContext<Self>,
 3957    ) {
 3958        self.transact(cx, |this, cx| {
 3959            if !this.select_autoclose_pair(cx) {
 3960                this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3961                    let line_mode = s.line_mode;
 3962                    s.move_with(|map, selection| {
 3963                        if selection.is_empty() && !line_mode {
 3964                            let cursor = movement::previous_subword_start(map, selection.head());
 3965                            selection.set_head(cursor, SelectionGoal::None);
 3966                        }
 3967                    });
 3968                });
 3969            }
 3970            this.insert("", cx);
 3971        });
 3972    }
 3973
 3974    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 3975        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3976            s.move_cursors_with(|map, head, _| {
 3977                (movement::next_word_end(map, head), SelectionGoal::None)
 3978            });
 3979        })
 3980    }
 3981
 3982    pub fn move_to_next_subword_end(
 3983        &mut self,
 3984        _: &MoveToNextSubwordEnd,
 3985        cx: &mut ViewContext<Self>,
 3986    ) {
 3987        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3988            s.move_cursors_with(|map, head, _| {
 3989                (movement::next_subword_end(map, head), SelectionGoal::None)
 3990            });
 3991        })
 3992    }
 3993
 3994    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 3995        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3996            s.move_heads_with(|map, head, _| {
 3997                (movement::next_word_end(map, head), SelectionGoal::None)
 3998            });
 3999        })
 4000    }
 4001
 4002    pub fn select_to_next_subword_end(
 4003        &mut self,
 4004        _: &SelectToNextSubwordEnd,
 4005        cx: &mut ViewContext<Self>,
 4006    ) {
 4007        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4008            s.move_heads_with(|map, head, _| {
 4009                (movement::next_subword_end(map, head), SelectionGoal::None)
 4010            });
 4011        })
 4012    }
 4013
 4014    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 4015        self.transact(cx, |this, cx| {
 4016            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4017                let line_mode = s.line_mode;
 4018                s.move_with(|map, selection| {
 4019                    if selection.is_empty() && !line_mode {
 4020                        let cursor = movement::next_word_end(map, selection.head());
 4021                        selection.set_head(cursor, SelectionGoal::None);
 4022                    }
 4023                });
 4024            });
 4025            this.insert("", cx);
 4026        });
 4027    }
 4028
 4029    pub fn delete_to_next_subword_end(
 4030        &mut self,
 4031        _: &DeleteToNextSubwordEnd,
 4032        cx: &mut ViewContext<Self>,
 4033    ) {
 4034        self.transact(cx, |this, cx| {
 4035            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4036                s.move_with(|map, selection| {
 4037                    if selection.is_empty() {
 4038                        let cursor = movement::next_subword_end(map, selection.head());
 4039                        selection.set_head(cursor, SelectionGoal::None);
 4040                    }
 4041                });
 4042            });
 4043            this.insert("", cx);
 4044        });
 4045    }
 4046
 4047    pub fn move_to_beginning_of_line(
 4048        &mut self,
 4049        _: &MoveToBeginningOfLine,
 4050        cx: &mut ViewContext<Self>,
 4051    ) {
 4052        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4053            s.move_cursors_with(|map, head, _| {
 4054                (
 4055                    movement::line_beginning(map, head, true),
 4056                    SelectionGoal::None,
 4057                )
 4058            });
 4059        })
 4060    }
 4061
 4062    pub fn select_to_beginning_of_line(
 4063        &mut self,
 4064        action: &SelectToBeginningOfLine,
 4065        cx: &mut ViewContext<Self>,
 4066    ) {
 4067        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4068            s.move_heads_with(|map, head, _| {
 4069                (
 4070                    movement::line_beginning(map, head, action.stop_at_soft_wraps),
 4071                    SelectionGoal::None,
 4072                )
 4073            });
 4074        });
 4075    }
 4076
 4077    pub fn delete_to_beginning_of_line(
 4078        &mut self,
 4079        _: &DeleteToBeginningOfLine,
 4080        cx: &mut ViewContext<Self>,
 4081    ) {
 4082        self.transact(cx, |this, cx| {
 4083            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4084                s.move_with(|_, selection| {
 4085                    selection.reversed = true;
 4086                });
 4087            });
 4088
 4089            this.select_to_beginning_of_line(
 4090                &SelectToBeginningOfLine {
 4091                    stop_at_soft_wraps: false,
 4092                },
 4093                cx,
 4094            );
 4095            this.backspace(&Backspace, cx);
 4096        });
 4097    }
 4098
 4099    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 4100        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4101            s.move_cursors_with(|map, head, _| {
 4102                (movement::line_end(map, head, true), SelectionGoal::None)
 4103            });
 4104        })
 4105    }
 4106
 4107    pub fn select_to_end_of_line(
 4108        &mut self,
 4109        action: &SelectToEndOfLine,
 4110        cx: &mut ViewContext<Self>,
 4111    ) {
 4112        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4113            s.move_heads_with(|map, head, _| {
 4114                (
 4115                    movement::line_end(map, head, action.stop_at_soft_wraps),
 4116                    SelectionGoal::None,
 4117                )
 4118            });
 4119        })
 4120    }
 4121
 4122    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 4123        self.transact(cx, |this, cx| {
 4124            this.select_to_end_of_line(
 4125                &SelectToEndOfLine {
 4126                    stop_at_soft_wraps: false,
 4127                },
 4128                cx,
 4129            );
 4130            this.delete(&Delete, cx);
 4131        });
 4132    }
 4133
 4134    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 4135        self.transact(cx, |this, cx| {
 4136            this.select_to_end_of_line(
 4137                &SelectToEndOfLine {
 4138                    stop_at_soft_wraps: false,
 4139                },
 4140                cx,
 4141            );
 4142            this.cut(&Cut, cx);
 4143        });
 4144    }
 4145
 4146    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 4147        if matches!(self.mode, EditorMode::SingleLine) {
 4148            cx.propagate_action();
 4149            return;
 4150        }
 4151
 4152        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4153            s.select_ranges(vec![0..0]);
 4154        });
 4155    }
 4156
 4157    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 4158        let mut selection = self.selections.last::<Point>(cx);
 4159        selection.set_head(Point::zero(), SelectionGoal::None);
 4160
 4161        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4162            s.select(vec![selection]);
 4163        });
 4164    }
 4165
 4166    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 4167        if matches!(self.mode, EditorMode::SingleLine) {
 4168            cx.propagate_action();
 4169            return;
 4170        }
 4171
 4172        let cursor = self.buffer.read(cx).read(cx).len();
 4173        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4174            s.select_ranges(vec![cursor..cursor])
 4175        });
 4176    }
 4177
 4178    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 4179        self.nav_history = nav_history;
 4180    }
 4181
 4182    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 4183        self.nav_history.as_ref()
 4184    }
 4185
 4186    fn push_to_nav_history(
 4187        &self,
 4188        position: Anchor,
 4189        new_position: Option<Point>,
 4190        cx: &mut ViewContext<Self>,
 4191    ) {
 4192        if let Some(nav_history) = &self.nav_history {
 4193            let buffer = self.buffer.read(cx).read(cx);
 4194            let point = position.to_point(&buffer);
 4195            let scroll_top_row = self.scroll_top_anchor.to_point(&buffer).row;
 4196            drop(buffer);
 4197
 4198            if let Some(new_position) = new_position {
 4199                let row_delta = (new_position.row as i64 - point.row as i64).abs();
 4200                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 4201                    return;
 4202                }
 4203            }
 4204
 4205            nav_history.push(
 4206                Some(NavigationData {
 4207                    cursor_anchor: position,
 4208                    cursor_position: point,
 4209                    scroll_position: self.scroll_position,
 4210                    scroll_top_anchor: self.scroll_top_anchor.clone(),
 4211                    scroll_top_row,
 4212                }),
 4213                cx,
 4214            );
 4215        }
 4216    }
 4217
 4218    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 4219        let buffer = self.buffer.read(cx).snapshot(cx);
 4220        let mut selection = self.selections.first::<usize>(cx);
 4221        selection.set_head(buffer.len(), SelectionGoal::None);
 4222        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4223            s.select(vec![selection]);
 4224        });
 4225    }
 4226
 4227    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 4228        let end = self.buffer.read(cx).read(cx).len();
 4229        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4230            s.select_ranges(vec![0..end]);
 4231        });
 4232    }
 4233
 4234    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 4235        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4236        let mut selections = self.selections.all::<Point>(cx);
 4237        let max_point = display_map.buffer_snapshot.max_point();
 4238        for selection in &mut selections {
 4239            let rows = selection.spanned_rows(true, &display_map);
 4240            selection.start = Point::new(rows.start, 0);
 4241            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 4242            selection.reversed = false;
 4243        }
 4244        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4245            s.select(selections);
 4246        });
 4247    }
 4248
 4249    pub fn split_selection_into_lines(
 4250        &mut self,
 4251        _: &SplitSelectionIntoLines,
 4252        cx: &mut ViewContext<Self>,
 4253    ) {
 4254        let mut to_unfold = Vec::new();
 4255        let mut new_selection_ranges = Vec::new();
 4256        {
 4257            let selections = self.selections.all::<Point>(cx);
 4258            let buffer = self.buffer.read(cx).read(cx);
 4259            for selection in selections {
 4260                for row in selection.start.row..selection.end.row {
 4261                    let cursor = Point::new(row, buffer.line_len(row));
 4262                    new_selection_ranges.push(cursor..cursor);
 4263                }
 4264                new_selection_ranges.push(selection.end..selection.end);
 4265                to_unfold.push(selection.start..selection.end);
 4266            }
 4267        }
 4268        self.unfold_ranges(to_unfold, true, cx);
 4269        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4270            s.select_ranges(new_selection_ranges);
 4271        });
 4272    }
 4273
 4274    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 4275        self.add_selection(true, cx);
 4276    }
 4277
 4278    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 4279        self.add_selection(false, cx);
 4280    }
 4281
 4282    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 4283        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4284        let mut selections = self.selections.all::<Point>(cx);
 4285        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 4286            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 4287            let range = oldest_selection.display_range(&display_map).sorted();
 4288            let columns = cmp::min(range.start.column(), range.end.column())
 4289                ..cmp::max(range.start.column(), range.end.column());
 4290
 4291            selections.clear();
 4292            let mut stack = Vec::new();
 4293            for row in range.start.row()..=range.end.row() {
 4294                if let Some(selection) = self.selections.build_columnar_selection(
 4295                    &display_map,
 4296                    row,
 4297                    &columns,
 4298                    oldest_selection.reversed,
 4299                ) {
 4300                    stack.push(selection.id);
 4301                    selections.push(selection);
 4302                }
 4303            }
 4304
 4305            if above {
 4306                stack.reverse();
 4307            }
 4308
 4309            AddSelectionsState { above, stack }
 4310        });
 4311
 4312        let last_added_selection = *state.stack.last().unwrap();
 4313        let mut new_selections = Vec::new();
 4314        if above == state.above {
 4315            let end_row = if above {
 4316                0
 4317            } else {
 4318                display_map.max_point().row()
 4319            };
 4320
 4321            'outer: for selection in selections {
 4322                if selection.id == last_added_selection {
 4323                    let range = selection.display_range(&display_map).sorted();
 4324                    debug_assert_eq!(range.start.row(), range.end.row());
 4325                    let mut row = range.start.row();
 4326                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
 4327                    {
 4328                        start..end
 4329                    } else {
 4330                        cmp::min(range.start.column(), range.end.column())
 4331                            ..cmp::max(range.start.column(), range.end.column())
 4332                    };
 4333
 4334                    while row != end_row {
 4335                        if above {
 4336                            row -= 1;
 4337                        } else {
 4338                            row += 1;
 4339                        }
 4340
 4341                        if let Some(new_selection) = self.selections.build_columnar_selection(
 4342                            &display_map,
 4343                            row,
 4344                            &columns,
 4345                            selection.reversed,
 4346                        ) {
 4347                            state.stack.push(new_selection.id);
 4348                            if above {
 4349                                new_selections.push(new_selection);
 4350                                new_selections.push(selection);
 4351                            } else {
 4352                                new_selections.push(selection);
 4353                                new_selections.push(new_selection);
 4354                            }
 4355
 4356                            continue 'outer;
 4357                        }
 4358                    }
 4359                }
 4360
 4361                new_selections.push(selection);
 4362            }
 4363        } else {
 4364            new_selections = selections;
 4365            new_selections.retain(|s| s.id != last_added_selection);
 4366            state.stack.pop();
 4367        }
 4368
 4369        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4370            s.select(new_selections);
 4371        });
 4372        if state.stack.len() > 1 {
 4373            self.add_selections_state = Some(state);
 4374        }
 4375    }
 4376
 4377    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
 4378        self.push_to_selection_history();
 4379        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4380        let buffer = &display_map.buffer_snapshot;
 4381        let mut selections = self.selections.all::<usize>(cx);
 4382        if let Some(mut select_next_state) = self.select_next_state.take() {
 4383            let query = &select_next_state.query;
 4384            if !select_next_state.done {
 4385                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 4386                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 4387                let mut next_selected_range = None;
 4388
 4389                let bytes_after_last_selection =
 4390                    buffer.bytes_in_range(last_selection.end..buffer.len());
 4391                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 4392                let query_matches = query
 4393                    .stream_find_iter(bytes_after_last_selection)
 4394                    .map(|result| (last_selection.end, result))
 4395                    .chain(
 4396                        query
 4397                            .stream_find_iter(bytes_before_first_selection)
 4398                            .map(|result| (0, result)),
 4399                    );
 4400                for (start_offset, query_match) in query_matches {
 4401                    let query_match = query_match.unwrap(); // can only fail due to I/O
 4402                    let offset_range =
 4403                        start_offset + query_match.start()..start_offset + query_match.end();
 4404                    let display_range = offset_range.start.to_display_point(&display_map)
 4405                        ..offset_range.end.to_display_point(&display_map);
 4406
 4407                    if !select_next_state.wordwise
 4408                        || (!movement::is_inside_word(&display_map, display_range.start)
 4409                            && !movement::is_inside_word(&display_map, display_range.end))
 4410                    {
 4411                        next_selected_range = Some(offset_range);
 4412                        break;
 4413                    }
 4414                }
 4415
 4416                if let Some(next_selected_range) = next_selected_range {
 4417                    self.unfold_ranges([next_selected_range.clone()], false, cx);
 4418                    self.change_selections(Some(Autoscroll::Newest), cx, |s| {
 4419                        if action.replace_newest {
 4420                            s.delete(s.newest_anchor().id);
 4421                        }
 4422                        s.insert_range(next_selected_range);
 4423                    });
 4424                } else {
 4425                    select_next_state.done = true;
 4426                }
 4427            }
 4428
 4429            self.select_next_state = Some(select_next_state);
 4430        } else if selections.len() == 1 {
 4431            let selection = selections.last_mut().unwrap();
 4432            if selection.start == selection.end {
 4433                let word_range = movement::surrounding_word(
 4434                    &display_map,
 4435                    selection.start.to_display_point(&display_map),
 4436                );
 4437                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 4438                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 4439                selection.goal = SelectionGoal::None;
 4440                selection.reversed = false;
 4441
 4442                let query = buffer
 4443                    .text_for_range(selection.start..selection.end)
 4444                    .collect::<String>();
 4445                let select_state = SelectNextState {
 4446                    query: AhoCorasick::new_auto_configured(&[query]),
 4447                    wordwise: true,
 4448                    done: false,
 4449                };
 4450                self.unfold_ranges([selection.start..selection.end], false, cx);
 4451                self.change_selections(Some(Autoscroll::Newest), cx, |s| {
 4452                    s.select(selections);
 4453                });
 4454                self.select_next_state = Some(select_state);
 4455            } else {
 4456                let query = buffer
 4457                    .text_for_range(selection.start..selection.end)
 4458                    .collect::<String>();
 4459                self.select_next_state = Some(SelectNextState {
 4460                    query: AhoCorasick::new_auto_configured(&[query]),
 4461                    wordwise: false,
 4462                    done: false,
 4463                });
 4464                self.select_next(action, cx);
 4465            }
 4466        }
 4467    }
 4468
 4469    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
 4470        self.transact(cx, |this, cx| {
 4471            let mut selections = this.selections.all::<Point>(cx);
 4472            let mut all_selection_lines_are_comments = true;
 4473            let mut edit_ranges = Vec::new();
 4474            let mut last_toggled_row = None;
 4475            this.buffer.update(cx, |buffer, cx| {
 4476                // TODO: Handle selections that cross excerpts
 4477                for selection in &mut selections {
 4478                    // Get the line comment prefix. Split its trailing whitespace into a separate string,
 4479                    // as that portion won't be used for detecting if a line is a comment.
 4480                    let full_comment_prefix: Arc<str> = if let Some(prefix) = buffer
 4481                        .language_at(selection.start, cx)
 4482                        .and_then(|l| l.line_comment_prefix())
 4483                    {
 4484                        prefix.into()
 4485                    } else {
 4486                        return;
 4487                    };
 4488                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 4489                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 4490                    edit_ranges.clear();
 4491                    let snapshot = buffer.snapshot(cx);
 4492
 4493                    let end_row =
 4494                        if selection.end.row > selection.start.row && selection.end.column == 0 {
 4495                            selection.end.row
 4496                        } else {
 4497                            selection.end.row + 1
 4498                        };
 4499
 4500                    for row in selection.start.row..end_row {
 4501                        // If multiple selections contain a given row, avoid processing that
 4502                        // row more than once.
 4503                        if last_toggled_row == Some(row) {
 4504                            continue;
 4505                        } else {
 4506                            last_toggled_row = Some(row);
 4507                        }
 4508
 4509                        if snapshot.is_line_blank(row) {
 4510                            continue;
 4511                        }
 4512
 4513                        let start = Point::new(row, snapshot.indent_size_for_line(row).len);
 4514                        let mut line_bytes = snapshot
 4515                            .bytes_in_range(start..snapshot.max_point())
 4516                            .flatten()
 4517                            .copied();
 4518
 4519                        // If this line currently begins with the line comment prefix, then record
 4520                        // the range containing the prefix.
 4521                        if all_selection_lines_are_comments
 4522                            && line_bytes
 4523                                .by_ref()
 4524                                .take(comment_prefix.len())
 4525                                .eq(comment_prefix.bytes())
 4526                        {
 4527                            // Include any whitespace that matches the comment prefix.
 4528                            let matching_whitespace_len = line_bytes
 4529                                .zip(comment_prefix_whitespace.bytes())
 4530                                .take_while(|(a, b)| a == b)
 4531                                .count()
 4532                                as u32;
 4533                            let end = Point::new(
 4534                                row,
 4535                                start.column
 4536                                    + comment_prefix.len() as u32
 4537                                    + matching_whitespace_len,
 4538                            );
 4539                            edit_ranges.push(start..end);
 4540                        }
 4541                        // If this line does not begin with the line comment prefix, then record
 4542                        // the position where the prefix should be inserted.
 4543                        else {
 4544                            all_selection_lines_are_comments = false;
 4545                            edit_ranges.push(start..start);
 4546                        }
 4547                    }
 4548
 4549                    if !edit_ranges.is_empty() {
 4550                        if all_selection_lines_are_comments {
 4551                            let empty_str: Arc<str> = "".into();
 4552                            buffer.edit(
 4553                                edit_ranges
 4554                                    .iter()
 4555                                    .cloned()
 4556                                    .map(|range| (range, empty_str.clone())),
 4557                                None,
 4558                                cx,
 4559                            );
 4560                        } else {
 4561                            let min_column =
 4562                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
 4563                            let edits = edit_ranges.iter().map(|range| {
 4564                                let position = Point::new(range.start.row, min_column);
 4565                                (position..position, full_comment_prefix.clone())
 4566                            });
 4567                            buffer.edit(edits, None, cx);
 4568                        }
 4569                    }
 4570                }
 4571            });
 4572
 4573            let selections = this.selections.all::<usize>(cx);
 4574            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 4575        });
 4576    }
 4577
 4578    pub fn select_larger_syntax_node(
 4579        &mut self,
 4580        _: &SelectLargerSyntaxNode,
 4581        cx: &mut ViewContext<Self>,
 4582    ) {
 4583        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4584        let buffer = self.buffer.read(cx).snapshot(cx);
 4585        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 4586
 4587        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4588        let mut selected_larger_node = false;
 4589        let new_selections = old_selections
 4590            .iter()
 4591            .map(|selection| {
 4592                let old_range = selection.start..selection.end;
 4593                let mut new_range = old_range.clone();
 4594                while let Some(containing_range) =
 4595                    buffer.range_for_syntax_ancestor(new_range.clone())
 4596                {
 4597                    new_range = containing_range;
 4598                    if !display_map.intersects_fold(new_range.start)
 4599                        && !display_map.intersects_fold(new_range.end)
 4600                    {
 4601                        break;
 4602                    }
 4603                }
 4604
 4605                selected_larger_node |= new_range != old_range;
 4606                Selection {
 4607                    id: selection.id,
 4608                    start: new_range.start,
 4609                    end: new_range.end,
 4610                    goal: SelectionGoal::None,
 4611                    reversed: selection.reversed,
 4612                }
 4613            })
 4614            .collect::<Vec<_>>();
 4615
 4616        if selected_larger_node {
 4617            stack.push(old_selections);
 4618            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4619                s.select(new_selections);
 4620            });
 4621        }
 4622        self.select_larger_syntax_node_stack = stack;
 4623    }
 4624
 4625    pub fn select_smaller_syntax_node(
 4626        &mut self,
 4627        _: &SelectSmallerSyntaxNode,
 4628        cx: &mut ViewContext<Self>,
 4629    ) {
 4630        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4631        if let Some(selections) = stack.pop() {
 4632            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4633                s.select(selections.to_vec());
 4634            });
 4635        }
 4636        self.select_larger_syntax_node_stack = stack;
 4637    }
 4638
 4639    pub fn move_to_enclosing_bracket(
 4640        &mut self,
 4641        _: &MoveToEnclosingBracket,
 4642        cx: &mut ViewContext<Self>,
 4643    ) {
 4644        let buffer = self.buffer.read(cx).snapshot(cx);
 4645        let mut selections = self.selections.all::<usize>(cx);
 4646        for selection in &mut selections {
 4647            if let Some((open_range, close_range)) =
 4648                buffer.enclosing_bracket_ranges(selection.start..selection.end)
 4649            {
 4650                let close_range = close_range.to_inclusive();
 4651                let destination = if close_range.contains(&selection.start)
 4652                    && close_range.contains(&selection.end)
 4653                {
 4654                    open_range.end
 4655                } else {
 4656                    *close_range.start()
 4657                };
 4658                selection.start = destination;
 4659                selection.end = destination;
 4660            }
 4661        }
 4662
 4663        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4664            s.select(selections);
 4665        });
 4666    }
 4667
 4668    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 4669        self.end_selection(cx);
 4670        self.selection_history.mode = SelectionHistoryMode::Undoing;
 4671        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 4672            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 4673            self.select_next_state = entry.select_next_state;
 4674            self.add_selections_state = entry.add_selections_state;
 4675            self.request_autoscroll(Autoscroll::Newest, cx);
 4676        }
 4677        self.selection_history.mode = SelectionHistoryMode::Normal;
 4678    }
 4679
 4680    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 4681        self.end_selection(cx);
 4682        self.selection_history.mode = SelectionHistoryMode::Redoing;
 4683        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 4684            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 4685            self.select_next_state = entry.select_next_state;
 4686            self.add_selections_state = entry.add_selections_state;
 4687            self.request_autoscroll(Autoscroll::Newest, cx);
 4688        }
 4689        self.selection_history.mode = SelectionHistoryMode::Normal;
 4690    }
 4691
 4692    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 4693        self.go_to_diagnostic_impl(Direction::Next, cx)
 4694    }
 4695
 4696    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 4697        self.go_to_diagnostic_impl(Direction::Prev, cx)
 4698    }
 4699
 4700    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 4701        let buffer = self.buffer.read(cx).snapshot(cx);
 4702        let selection = self.selections.newest::<usize>(cx);
 4703
 4704        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
 4705        if direction == Direction::Next {
 4706            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 4707                let (group_id, jump_to) = popover.activation_info();
 4708                if self.activate_diagnostics(group_id, cx) {
 4709                    self.change_selections(Some(Autoscroll::Center), cx, |s| {
 4710                        let mut new_selection = s.newest_anchor().clone();
 4711                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 4712                        s.select_anchors(vec![new_selection.clone()]);
 4713                    });
 4714                }
 4715                return;
 4716            }
 4717        }
 4718
 4719        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 4720            active_diagnostics
 4721                .primary_range
 4722                .to_offset(&buffer)
 4723                .to_inclusive()
 4724        });
 4725        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 4726            if active_primary_range.contains(&selection.head()) {
 4727                *active_primary_range.end()
 4728            } else {
 4729                selection.head()
 4730            }
 4731        } else {
 4732            selection.head()
 4733        };
 4734
 4735        loop {
 4736            let mut diagnostics = if direction == Direction::Prev {
 4737                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 4738            } else {
 4739                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 4740            };
 4741            let group = diagnostics.find_map(|entry| {
 4742                if entry.diagnostic.is_primary
 4743                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 4744                    && !entry.range.is_empty()
 4745                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 4746                {
 4747                    Some((entry.range, entry.diagnostic.group_id))
 4748                } else {
 4749                    None
 4750                }
 4751            });
 4752
 4753            if let Some((primary_range, group_id)) = group {
 4754                if self.activate_diagnostics(group_id, cx) {
 4755                    self.change_selections(Some(Autoscroll::Center), cx, |s| {
 4756                        s.select(vec![Selection {
 4757                            id: selection.id,
 4758                            start: primary_range.start,
 4759                            end: primary_range.start,
 4760                            reversed: false,
 4761                            goal: SelectionGoal::None,
 4762                        }]);
 4763                    });
 4764                }
 4765                break;
 4766            } else {
 4767                // Cycle around to the start of the buffer, potentially moving back to the start of
 4768                // the currently active diagnostic.
 4769                active_primary_range.take();
 4770                if direction == Direction::Prev {
 4771                    if search_start == buffer.len() {
 4772                        break;
 4773                    } else {
 4774                        search_start = buffer.len();
 4775                    }
 4776                } else {
 4777                    if search_start == 0 {
 4778                        break;
 4779                    } else {
 4780                        search_start = 0;
 4781                    }
 4782                }
 4783            }
 4784        }
 4785    }
 4786
 4787    pub fn go_to_definition(
 4788        workspace: &mut Workspace,
 4789        _: &GoToDefinition,
 4790        cx: &mut ViewContext<Workspace>,
 4791    ) {
 4792        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
 4793    }
 4794
 4795    pub fn go_to_type_definition(
 4796        workspace: &mut Workspace,
 4797        _: &GoToTypeDefinition,
 4798        cx: &mut ViewContext<Workspace>,
 4799    ) {
 4800        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
 4801    }
 4802
 4803    fn go_to_definition_of_kind(
 4804        kind: GotoDefinitionKind,
 4805        workspace: &mut Workspace,
 4806        cx: &mut ViewContext<Workspace>,
 4807    ) {
 4808        let active_item = workspace.active_item(cx);
 4809        let editor_handle = if let Some(editor) = active_item
 4810            .as_ref()
 4811            .and_then(|item| item.act_as::<Self>(cx))
 4812        {
 4813            editor
 4814        } else {
 4815            return;
 4816        };
 4817
 4818        let editor = editor_handle.read(cx);
 4819        let buffer = editor.buffer.read(cx);
 4820        let head = editor.selections.newest::<usize>(cx).head();
 4821        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 4822            text_anchor
 4823        } else {
 4824            return;
 4825        };
 4826
 4827        let project = workspace.project().clone();
 4828        let definitions = project.update(cx, |project, cx| match kind {
 4829            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 4830            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 4831        });
 4832
 4833        cx.spawn(|workspace, mut cx| async move {
 4834            let definitions = definitions.await?;
 4835            workspace.update(&mut cx, |workspace, cx| {
 4836                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
 4837            });
 4838
 4839            Ok::<(), anyhow::Error>(())
 4840        })
 4841        .detach_and_log_err(cx);
 4842    }
 4843
 4844    pub fn navigate_to_definitions(
 4845        workspace: &mut Workspace,
 4846        editor_handle: ViewHandle<Editor>,
 4847        definitions: Vec<LocationLink>,
 4848        cx: &mut ViewContext<Workspace>,
 4849    ) {
 4850        let pane = workspace.active_pane().clone();
 4851        for definition in definitions {
 4852            let range = definition
 4853                .target
 4854                .range
 4855                .to_offset(definition.target.buffer.read(cx));
 4856
 4857            let target_editor_handle = workspace.open_project_item(definition.target.buffer, cx);
 4858            target_editor_handle.update(cx, |target_editor, cx| {
 4859                // When selecting a definition in a different buffer, disable the nav history
 4860                // to avoid creating a history entry at the previous cursor location.
 4861                if editor_handle != target_editor_handle {
 4862                    pane.update(cx, |pane, _| pane.disable_history());
 4863                }
 4864                target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
 4865                    s.select_ranges([range]);
 4866                });
 4867
 4868                pane.update(cx, |pane, _| pane.enable_history());
 4869            });
 4870        }
 4871    }
 4872
 4873    pub fn find_all_references(
 4874        workspace: &mut Workspace,
 4875        _: &FindAllReferences,
 4876        cx: &mut ViewContext<Workspace>,
 4877    ) -> Option<Task<Result<()>>> {
 4878        let active_item = workspace.active_item(cx)?;
 4879        let editor_handle = active_item.act_as::<Self>(cx)?;
 4880
 4881        let editor = editor_handle.read(cx);
 4882        let buffer = editor.buffer.read(cx);
 4883        let head = editor.selections.newest::<usize>(cx).head();
 4884        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 4885        let replica_id = editor.replica_id(cx);
 4886
 4887        let project = workspace.project().clone();
 4888        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 4889        Some(cx.spawn(|workspace, mut cx| async move {
 4890            let mut locations = references.await?;
 4891            if locations.is_empty() {
 4892                return Ok(());
 4893            }
 4894
 4895            locations.sort_by_key(|location| location.buffer.id());
 4896            let mut locations = locations.into_iter().peekable();
 4897            let mut ranges_to_highlight = Vec::new();
 4898
 4899            let excerpt_buffer = cx.add_model(|cx| {
 4900                let mut symbol_name = None;
 4901                let mut multibuffer = MultiBuffer::new(replica_id);
 4902                while let Some(location) = locations.next() {
 4903                    let buffer = location.buffer.read(cx);
 4904                    let mut ranges_for_buffer = Vec::new();
 4905                    let range = location.range.to_offset(buffer);
 4906                    ranges_for_buffer.push(range.clone());
 4907                    if symbol_name.is_none() {
 4908                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 4909                    }
 4910
 4911                    while let Some(next_location) = locations.peek() {
 4912                        if next_location.buffer == location.buffer {
 4913                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 4914                            locations.next();
 4915                        } else {
 4916                            break;
 4917                        }
 4918                    }
 4919
 4920                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 4921                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 4922                        location.buffer.clone(),
 4923                        ranges_for_buffer,
 4924                        1,
 4925                        cx,
 4926                    ));
 4927                }
 4928                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 4929            });
 4930
 4931            workspace.update(&mut cx, |workspace, cx| {
 4932                let editor =
 4933                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 4934                editor.update(cx, |editor, cx| {
 4935                    editor.highlight_background::<Self>(
 4936                        ranges_to_highlight,
 4937                        |theme| theme.editor.highlighted_line_background,
 4938                        cx,
 4939                    );
 4940                });
 4941                workspace.add_item(Box::new(editor), cx);
 4942            });
 4943
 4944            Ok(())
 4945        }))
 4946    }
 4947
 4948    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4949        use language::ToOffset as _;
 4950
 4951        let project = self.project.clone()?;
 4952        let selection = self.selections.newest_anchor().clone();
 4953        let (cursor_buffer, cursor_buffer_position) = self
 4954            .buffer
 4955            .read(cx)
 4956            .text_anchor_for_position(selection.head(), cx)?;
 4957        let (tail_buffer, _) = self
 4958            .buffer
 4959            .read(cx)
 4960            .text_anchor_for_position(selection.tail(), cx)?;
 4961        if tail_buffer != cursor_buffer {
 4962            return None;
 4963        }
 4964
 4965        let snapshot = cursor_buffer.read(cx).snapshot();
 4966        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4967        let prepare_rename = project.update(cx, |project, cx| {
 4968            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4969        });
 4970
 4971        Some(cx.spawn(|this, mut cx| async move {
 4972            let rename_range = if let Some(range) = prepare_rename.await? {
 4973                Some(range)
 4974            } else {
 4975                this.read_with(&cx, |this, cx| {
 4976                    let buffer = this.buffer.read(cx).snapshot(cx);
 4977                    let mut buffer_highlights = this
 4978                        .document_highlights_for_position(selection.head(), &buffer)
 4979                        .filter(|highlight| {
 4980                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 4981                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 4982                        });
 4983                    buffer_highlights
 4984                        .next()
 4985                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 4986                })
 4987            };
 4988            if let Some(rename_range) = rename_range {
 4989                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4990                let cursor_offset_in_rename_range =
 4991                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4992
 4993                this.update(&mut cx, |this, cx| {
 4994                    this.take_rename(false, cx);
 4995                    let style = this.style(cx);
 4996                    let buffer = this.buffer.read(cx).read(cx);
 4997                    let cursor_offset = selection.head().to_offset(&buffer);
 4998                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4999                    let rename_end = rename_start + rename_buffer_range.len();
 5000                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 5001                    let mut old_highlight_id = None;
 5002                    let old_name: Arc<str> = buffer
 5003                        .chunks(rename_start..rename_end, true)
 5004                        .map(|chunk| {
 5005                            if old_highlight_id.is_none() {
 5006                                old_highlight_id = chunk.syntax_highlight_id;
 5007                            }
 5008                            chunk.text
 5009                        })
 5010                        .collect::<String>()
 5011                        .into();
 5012
 5013                    drop(buffer);
 5014
 5015                    // Position the selection in the rename editor so that it matches the current selection.
 5016                    this.show_local_selections = false;
 5017                    let rename_editor = cx.add_view(|cx| {
 5018                        let mut editor = Editor::single_line(None, cx);
 5019                        if let Some(old_highlight_id) = old_highlight_id {
 5020                            editor.override_text_style =
 5021                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 5022                        }
 5023                        editor.buffer.update(cx, |buffer, cx| {
 5024                            buffer.edit([(0..0, old_name.clone())], None, cx)
 5025                        });
 5026                        editor.select_all(&SelectAll, cx);
 5027                        editor
 5028                    });
 5029
 5030                    let ranges = this
 5031                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 5032                        .into_iter()
 5033                        .flat_map(|(_, ranges)| ranges)
 5034                        .chain(
 5035                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 5036                                .into_iter()
 5037                                .flat_map(|(_, ranges)| ranges),
 5038                        )
 5039                        .collect();
 5040
 5041                    this.highlight_text::<Rename>(
 5042                        ranges,
 5043                        HighlightStyle {
 5044                            fade_out: Some(style.rename_fade),
 5045                            ..Default::default()
 5046                        },
 5047                        cx,
 5048                    );
 5049                    cx.focus(&rename_editor);
 5050                    let block_id = this.insert_blocks(
 5051                        [BlockProperties {
 5052                            style: BlockStyle::Flex,
 5053                            position: range.start.clone(),
 5054                            height: 1,
 5055                            render: Arc::new({
 5056                                let editor = rename_editor.clone();
 5057                                move |cx: &mut BlockContext| {
 5058                                    ChildView::new(editor.clone())
 5059                                        .contained()
 5060                                        .with_padding_left(cx.anchor_x)
 5061                                        .boxed()
 5062                                }
 5063                            }),
 5064                            disposition: BlockDisposition::Below,
 5065                        }],
 5066                        cx,
 5067                    )[0];
 5068                    this.pending_rename = Some(RenameState {
 5069                        range,
 5070                        old_name,
 5071                        editor: rename_editor,
 5072                        block_id,
 5073                    });
 5074                });
 5075            }
 5076
 5077            Ok(())
 5078        }))
 5079    }
 5080
 5081    pub fn confirm_rename(
 5082        workspace: &mut Workspace,
 5083        _: &ConfirmRename,
 5084        cx: &mut ViewContext<Workspace>,
 5085    ) -> Option<Task<Result<()>>> {
 5086        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 5087
 5088        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 5089            let rename = editor.take_rename(false, cx)?;
 5090            let buffer = editor.buffer.read(cx);
 5091            let (start_buffer, start) =
 5092                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 5093            let (end_buffer, end) =
 5094                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 5095            if start_buffer == end_buffer {
 5096                let new_name = rename.editor.read(cx).text(cx);
 5097                Some((start_buffer, start..end, rename.old_name, new_name))
 5098            } else {
 5099                None
 5100            }
 5101        })?;
 5102
 5103        let rename = workspace.project().clone().update(cx, |project, cx| {
 5104            project.perform_rename(
 5105                buffer.clone(),
 5106                range.start.clone(),
 5107                new_name.clone(),
 5108                true,
 5109                cx,
 5110            )
 5111        });
 5112
 5113        Some(cx.spawn(|workspace, mut cx| async move {
 5114            let project_transaction = rename.await?;
 5115            Self::open_project_transaction(
 5116                editor.clone(),
 5117                workspace,
 5118                project_transaction,
 5119                format!("Rename: {}{}", old_name, new_name),
 5120                cx.clone(),
 5121            )
 5122            .await?;
 5123
 5124            editor.update(&mut cx, |editor, cx| {
 5125                editor.refresh_document_highlights(cx);
 5126            });
 5127            Ok(())
 5128        }))
 5129    }
 5130
 5131    fn take_rename(
 5132        &mut self,
 5133        moving_cursor: bool,
 5134        cx: &mut ViewContext<Self>,
 5135    ) -> Option<RenameState> {
 5136        let rename = self.pending_rename.take()?;
 5137        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 5138        self.clear_text_highlights::<Rename>(cx);
 5139        self.show_local_selections = true;
 5140
 5141        if moving_cursor {
 5142            let rename_editor = rename.editor.read(cx);
 5143            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 5144
 5145            // Update the selection to match the position of the selection inside
 5146            // the rename editor.
 5147            let snapshot = self.buffer.read(cx).read(cx);
 5148            let rename_range = rename.range.to_offset(&snapshot);
 5149            let cursor_in_editor = snapshot
 5150                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 5151                .min(rename_range.end);
 5152            drop(snapshot);
 5153
 5154            self.change_selections(None, cx, |s| {
 5155                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 5156            });
 5157        } else {
 5158            self.refresh_document_highlights(cx);
 5159        }
 5160
 5161        Some(rename)
 5162    }
 5163
 5164    #[cfg(any(test, feature = "test-support"))]
 5165    pub fn pending_rename(&self) -> Option<&RenameState> {
 5166        self.pending_rename.as_ref()
 5167    }
 5168
 5169    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 5170        if let Some(project) = self.project.clone() {
 5171            self.buffer.update(cx, |multi_buffer, cx| {
 5172                project.update(cx, |project, cx| {
 5173                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 5174                });
 5175            })
 5176        }
 5177    }
 5178
 5179    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 5180        cx.show_character_palette();
 5181    }
 5182
 5183    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 5184        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 5185            let buffer = self.buffer.read(cx).snapshot(cx);
 5186            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 5187            let is_valid = buffer
 5188                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 5189                .any(|entry| {
 5190                    entry.diagnostic.is_primary
 5191                        && !entry.range.is_empty()
 5192                        && entry.range.start == primary_range_start
 5193                        && entry.diagnostic.message == active_diagnostics.primary_message
 5194                });
 5195
 5196            if is_valid != active_diagnostics.is_valid {
 5197                active_diagnostics.is_valid = is_valid;
 5198                let mut new_styles = HashMap::default();
 5199                for (block_id, diagnostic) in &active_diagnostics.blocks {
 5200                    new_styles.insert(
 5201                        *block_id,
 5202                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 5203                    );
 5204                }
 5205                self.display_map
 5206                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 5207            }
 5208        }
 5209    }
 5210
 5211    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 5212        self.dismiss_diagnostics(cx);
 5213        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 5214            let buffer = self.buffer.read(cx).snapshot(cx);
 5215
 5216            let mut primary_range = None;
 5217            let mut primary_message = None;
 5218            let mut group_end = Point::zero();
 5219            let diagnostic_group = buffer
 5220                .diagnostic_group::<Point>(group_id)
 5221                .map(|entry| {
 5222                    if entry.range.end > group_end {
 5223                        group_end = entry.range.end;
 5224                    }
 5225                    if entry.diagnostic.is_primary {
 5226                        primary_range = Some(entry.range.clone());
 5227                        primary_message = Some(entry.diagnostic.message.clone());
 5228                    }
 5229                    entry
 5230                })
 5231                .collect::<Vec<_>>();
 5232            let primary_range = primary_range?;
 5233            let primary_message = primary_message?;
 5234            let primary_range =
 5235                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 5236
 5237            let blocks = display_map
 5238                .insert_blocks(
 5239                    diagnostic_group.iter().map(|entry| {
 5240                        let diagnostic = entry.diagnostic.clone();
 5241                        let message_height = diagnostic.message.lines().count() as u8;
 5242                        BlockProperties {
 5243                            style: BlockStyle::Fixed,
 5244                            position: buffer.anchor_after(entry.range.start),
 5245                            height: message_height,
 5246                            render: diagnostic_block_renderer(diagnostic, true),
 5247                            disposition: BlockDisposition::Below,
 5248                        }
 5249                    }),
 5250                    cx,
 5251                )
 5252                .into_iter()
 5253                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 5254                .collect();
 5255
 5256            Some(ActiveDiagnosticGroup {
 5257                primary_range,
 5258                primary_message,
 5259                blocks,
 5260                is_valid: true,
 5261            })
 5262        });
 5263        self.active_diagnostics.is_some()
 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 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        "});
 8207        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8208        cx.assert_editor_state(indoc! {"
 8209                «oneˇ» «twoˇ»
 8210            three
 8211             four
 8212        "});
 8213
 8214        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8215        cx.assert_editor_state(indoc! {"
 8216            «oneˇ» «twoˇ»
 8217            three
 8218             four
 8219        "});
 8220
 8221        // select across line ending
 8222        cx.set_state(indoc! {"
 8223            one two
 8224            t«hree
 8225            ˇ» four
 8226        "});
 8227        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8228        cx.assert_editor_state(indoc! {"
 8229            one two
 8230                t«hree
 8231            ˇ» four
 8232        "});
 8233
 8234        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8235        cx.assert_editor_state(indoc! {"
 8236            one two
 8237            t«hree
 8238            ˇ» four
 8239        "});
 8240
 8241        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8242        cx.set_state(indoc! {"
 8243            one two
 8244            ˇthree
 8245                four
 8246        "});
 8247        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8248        cx.assert_editor_state(indoc! {"
 8249            one two
 8250                ˇthree
 8251                four
 8252        "});
 8253
 8254        cx.set_state(indoc! {"
 8255            one two
 8256            ˇ    three
 8257             four
 8258        "});
 8259        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8260        cx.assert_editor_state(indoc! {"
 8261            one two
 8262            ˇthree
 8263             four
 8264        "});
 8265    }
 8266
 8267    #[gpui::test]
 8268    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 8269        let mut cx = EditorTestContext::new(cx).await;
 8270        cx.update(|cx| {
 8271            cx.update_global::<Settings, _, _>(|settings, _| {
 8272                settings.editor_overrides.hard_tabs = Some(true);
 8273            });
 8274        });
 8275
 8276        // select two ranges on one line
 8277        cx.set_state(indoc! {"
 8278            «oneˇ» «twoˇ»
 8279            three
 8280            four
 8281        "});
 8282        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8283        cx.assert_editor_state(indoc! {"
 8284            \t«oneˇ» «twoˇ»
 8285            three
 8286            four
 8287        "});
 8288        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8289        cx.assert_editor_state(indoc! {"
 8290            \t\t«oneˇ» «twoˇ»
 8291            three
 8292            four
 8293        "});
 8294        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8295        cx.assert_editor_state(indoc! {"
 8296            \t«oneˇ» «twoˇ»
 8297            three
 8298            four
 8299        "});
 8300        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8301        cx.assert_editor_state(indoc! {"
 8302            «oneˇ» «twoˇ»
 8303            three
 8304            four
 8305        "});
 8306
 8307        // select across a line ending
 8308        cx.set_state(indoc! {"
 8309            one two
 8310            t«hree
 8311            ˇ»four
 8312        "});
 8313        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8314        cx.assert_editor_state(indoc! {"
 8315            one two
 8316            \tt«hree
 8317            ˇ»four
 8318        "});
 8319        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8320        cx.assert_editor_state(indoc! {"
 8321            one two
 8322            \t\tt«hree
 8323            ˇ»four
 8324        "});
 8325        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8326        cx.assert_editor_state(indoc! {"
 8327            one two
 8328            \tt«hree
 8329            ˇ»four
 8330        "});
 8331        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8332        cx.assert_editor_state(indoc! {"
 8333            one two
 8334            t«hree
 8335            ˇ»four
 8336        "});
 8337
 8338        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8339        cx.set_state(indoc! {"
 8340            one two
 8341            ˇthree
 8342            four
 8343        "});
 8344        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8345        cx.assert_editor_state(indoc! {"
 8346            one two
 8347            ˇthree
 8348            four
 8349        "});
 8350        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8351        cx.assert_editor_state(indoc! {"
 8352            one two
 8353            \tˇthree
 8354            four
 8355        "});
 8356        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8357        cx.assert_editor_state(indoc! {"
 8358            one two
 8359            ˇthree
 8360            four
 8361        "});
 8362    }
 8363
 8364    #[gpui::test]
 8365    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 8366        cx.set_global(
 8367            Settings::test(cx)
 8368                .with_language_defaults(
 8369                    "TOML",
 8370                    EditorSettings {
 8371                        tab_size: Some(2.try_into().unwrap()),
 8372                        ..Default::default()
 8373                    },
 8374                )
 8375                .with_language_defaults(
 8376                    "Rust",
 8377                    EditorSettings {
 8378                        tab_size: Some(4.try_into().unwrap()),
 8379                        ..Default::default()
 8380                    },
 8381                ),
 8382        );
 8383        let toml_language = Arc::new(Language::new(
 8384            LanguageConfig {
 8385                name: "TOML".into(),
 8386                ..Default::default()
 8387            },
 8388            None,
 8389        ));
 8390        let rust_language = Arc::new(Language::new(
 8391            LanguageConfig {
 8392                name: "Rust".into(),
 8393                ..Default::default()
 8394            },
 8395            None,
 8396        ));
 8397
 8398        let toml_buffer = cx
 8399            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 8400        let rust_buffer = cx.add_model(|cx| {
 8401            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 8402        });
 8403        let multibuffer = cx.add_model(|cx| {
 8404            let mut multibuffer = MultiBuffer::new(0);
 8405            multibuffer.push_excerpts(
 8406                toml_buffer.clone(),
 8407                [ExcerptRange {
 8408                    context: Point::new(0, 0)..Point::new(2, 0),
 8409                    primary: None,
 8410                }],
 8411                cx,
 8412            );
 8413            multibuffer.push_excerpts(
 8414                rust_buffer.clone(),
 8415                [ExcerptRange {
 8416                    context: Point::new(0, 0)..Point::new(1, 0),
 8417                    primary: None,
 8418                }],
 8419                cx,
 8420            );
 8421            multibuffer
 8422        });
 8423
 8424        cx.add_window(Default::default(), |cx| {
 8425            let mut editor = build_editor(multibuffer, cx);
 8426
 8427            assert_eq!(
 8428                editor.text(cx),
 8429                indoc! {"
 8430                    a = 1
 8431                    b = 2
 8432
 8433                    const c: usize = 3;
 8434                "}
 8435            );
 8436
 8437            select_ranges(
 8438                &mut editor,
 8439                indoc! {"
 8440                    «aˇ» = 1
 8441                    b = 2
 8442
 8443                    «const c:ˇ» usize = 3;
 8444                "},
 8445                cx,
 8446            );
 8447
 8448            editor.tab(&Tab, cx);
 8449            assert_text_with_selections(
 8450                &mut editor,
 8451                indoc! {"
 8452                      «aˇ» = 1
 8453                    b = 2
 8454
 8455                        «const c:ˇ» usize = 3;
 8456                "},
 8457                cx,
 8458            );
 8459            editor.tab_prev(&TabPrev, cx);
 8460            assert_text_with_selections(
 8461                &mut editor,
 8462                indoc! {"
 8463                    «aˇ» = 1
 8464                    b = 2
 8465
 8466                    «const c:ˇ» usize = 3;
 8467                "},
 8468                cx,
 8469            );
 8470
 8471            editor
 8472        });
 8473    }
 8474
 8475    #[gpui::test]
 8476    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 8477        let mut cx = EditorTestContext::new(cx).await;
 8478
 8479        // Basic backspace
 8480        cx.set_state(indoc! {"
 8481            onˇe two three
 8482            fou«rˇ» five six
 8483            seven «ˇeight nine
 8484            »ten
 8485        "});
 8486        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8487        cx.assert_editor_state(indoc! {"
 8488            oˇe two three
 8489            fouˇ five six
 8490            seven ˇten
 8491        "});
 8492
 8493        // Test backspace inside and around indents
 8494        cx.set_state(indoc! {"
 8495            zero
 8496                ˇone
 8497                    ˇtwo
 8498                ˇ ˇ ˇ  three
 8499            ˇ  ˇ  four
 8500        "});
 8501        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8502        cx.assert_editor_state(indoc! {"
 8503            zero
 8504            ˇone
 8505                ˇtwo
 8506            ˇ  threeˇ  four
 8507        "});
 8508
 8509        // Test backspace with line_mode set to true
 8510        cx.update_editor(|e, _| e.selections.line_mode = true);
 8511        cx.set_state(indoc! {"
 8512            The ˇquick ˇbrown
 8513            fox jumps over
 8514            the lazy dog
 8515            ˇThe qu«ick bˇ»rown"});
 8516        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8517        cx.assert_editor_state(indoc! {"
 8518            ˇfox jumps over
 8519            the lazy dogˇ"});
 8520    }
 8521
 8522    #[gpui::test]
 8523    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8524        let mut cx = EditorTestContext::new(cx).await;
 8525
 8526        cx.set_state(indoc! {"
 8527            onˇe two three
 8528            fou«rˇ» five six
 8529            seven «ˇeight nine
 8530            »ten
 8531        "});
 8532        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8533        cx.assert_editor_state(indoc! {"
 8534            onˇ two three
 8535            fouˇ five six
 8536            seven ˇten
 8537        "});
 8538
 8539        // Test backspace with line_mode set to true
 8540        cx.update_editor(|e, _| e.selections.line_mode = true);
 8541        cx.set_state(indoc! {"
 8542            The ˇquick ˇbrown
 8543            fox «ˇjum»ps over
 8544            the lazy dog
 8545            ˇThe qu«ick bˇ»rown"});
 8546        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8547        cx.assert_editor_state("ˇthe lazy dogˇ");
 8548    }
 8549
 8550    #[gpui::test]
 8551    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8552        cx.set_global(Settings::test(cx));
 8553        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8554        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8555        view.update(cx, |view, cx| {
 8556            view.change_selections(None, cx, |s| {
 8557                s.select_display_ranges([
 8558                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8559                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8560                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8561                ])
 8562            });
 8563            view.delete_line(&DeleteLine, cx);
 8564            assert_eq!(view.display_text(cx), "ghi");
 8565            assert_eq!(
 8566                view.selections.display_ranges(cx),
 8567                vec![
 8568                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8569                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8570                ]
 8571            );
 8572        });
 8573
 8574        cx.set_global(Settings::test(cx));
 8575        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8576        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8577        view.update(cx, |view, cx| {
 8578            view.change_selections(None, cx, |s| {
 8579                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8580            });
 8581            view.delete_line(&DeleteLine, cx);
 8582            assert_eq!(view.display_text(cx), "ghi\n");
 8583            assert_eq!(
 8584                view.selections.display_ranges(cx),
 8585                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8586            );
 8587        });
 8588    }
 8589
 8590    #[gpui::test]
 8591    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8592        cx.set_global(Settings::test(cx));
 8593        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8594        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8595        view.update(cx, |view, cx| {
 8596            view.change_selections(None, cx, |s| {
 8597                s.select_display_ranges([
 8598                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8599                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8600                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8601                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8602                ])
 8603            });
 8604            view.duplicate_line(&DuplicateLine, cx);
 8605            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8606            assert_eq!(
 8607                view.selections.display_ranges(cx),
 8608                vec![
 8609                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8610                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8611                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8612                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8613                ]
 8614            );
 8615        });
 8616
 8617        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8618        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8619        view.update(cx, |view, cx| {
 8620            view.change_selections(None, cx, |s| {
 8621                s.select_display_ranges([
 8622                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8623                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8624                ])
 8625            });
 8626            view.duplicate_line(&DuplicateLine, cx);
 8627            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8628            assert_eq!(
 8629                view.selections.display_ranges(cx),
 8630                vec![
 8631                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8632                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8633                ]
 8634            );
 8635        });
 8636    }
 8637
 8638    #[gpui::test]
 8639    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8640        cx.set_global(Settings::test(cx));
 8641        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8642        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8643        view.update(cx, |view, cx| {
 8644            view.fold_ranges(
 8645                vec![
 8646                    Point::new(0, 2)..Point::new(1, 2),
 8647                    Point::new(2, 3)..Point::new(4, 1),
 8648                    Point::new(7, 0)..Point::new(8, 4),
 8649                ],
 8650                cx,
 8651            );
 8652            view.change_selections(None, cx, |s| {
 8653                s.select_display_ranges([
 8654                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8655                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8656                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8657                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8658                ])
 8659            });
 8660            assert_eq!(
 8661                view.display_text(cx),
 8662                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8663            );
 8664
 8665            view.move_line_up(&MoveLineUp, cx);
 8666            assert_eq!(
 8667                view.display_text(cx),
 8668                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8669            );
 8670            assert_eq!(
 8671                view.selections.display_ranges(cx),
 8672                vec![
 8673                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8674                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8675                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8676                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8677                ]
 8678            );
 8679        });
 8680
 8681        view.update(cx, |view, cx| {
 8682            view.move_line_down(&MoveLineDown, cx);
 8683            assert_eq!(
 8684                view.display_text(cx),
 8685                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8686            );
 8687            assert_eq!(
 8688                view.selections.display_ranges(cx),
 8689                vec![
 8690                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8691                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8692                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8693                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8694                ]
 8695            );
 8696        });
 8697
 8698        view.update(cx, |view, cx| {
 8699            view.move_line_down(&MoveLineDown, cx);
 8700            assert_eq!(
 8701                view.display_text(cx),
 8702                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8703            );
 8704            assert_eq!(
 8705                view.selections.display_ranges(cx),
 8706                vec![
 8707                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8708                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8709                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8710                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8711                ]
 8712            );
 8713        });
 8714
 8715        view.update(cx, |view, cx| {
 8716            view.move_line_up(&MoveLineUp, cx);
 8717            assert_eq!(
 8718                view.display_text(cx),
 8719                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8720            );
 8721            assert_eq!(
 8722                view.selections.display_ranges(cx),
 8723                vec![
 8724                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8725                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8726                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8727                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8728                ]
 8729            );
 8730        });
 8731    }
 8732
 8733    #[gpui::test]
 8734    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8735        cx.set_global(Settings::test(cx));
 8736        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8737        let snapshot = buffer.read(cx).snapshot(cx);
 8738        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8739        editor.update(cx, |editor, cx| {
 8740            editor.insert_blocks(
 8741                [BlockProperties {
 8742                    style: BlockStyle::Fixed,
 8743                    position: snapshot.anchor_after(Point::new(2, 0)),
 8744                    disposition: BlockDisposition::Below,
 8745                    height: 1,
 8746                    render: Arc::new(|_| Empty::new().boxed()),
 8747                }],
 8748                cx,
 8749            );
 8750            editor.change_selections(None, cx, |s| {
 8751                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8752            });
 8753            editor.move_line_down(&MoveLineDown, cx);
 8754        });
 8755    }
 8756
 8757    #[gpui::test]
 8758    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8759        cx.set_global(Settings::test(cx));
 8760
 8761        cx.add_window(Default::default(), |cx| {
 8762            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8763
 8764            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8765            editor.transpose(&Default::default(), cx);
 8766            assert_eq!(editor.text(cx), "bac");
 8767            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8768
 8769            editor.transpose(&Default::default(), cx);
 8770            assert_eq!(editor.text(cx), "bca");
 8771            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8772
 8773            editor.transpose(&Default::default(), cx);
 8774            assert_eq!(editor.text(cx), "bac");
 8775            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8776
 8777            editor
 8778        })
 8779        .1;
 8780
 8781        cx.add_window(Default::default(), |cx| {
 8782            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8783
 8784            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8785            editor.transpose(&Default::default(), cx);
 8786            assert_eq!(editor.text(cx), "acb\nde");
 8787            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8788
 8789            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8790            editor.transpose(&Default::default(), cx);
 8791            assert_eq!(editor.text(cx), "acbd\ne");
 8792            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8793
 8794            editor.transpose(&Default::default(), cx);
 8795            assert_eq!(editor.text(cx), "acbde\n");
 8796            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8797
 8798            editor.transpose(&Default::default(), cx);
 8799            assert_eq!(editor.text(cx), "acbd\ne");
 8800            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8801
 8802            editor
 8803        })
 8804        .1;
 8805
 8806        cx.add_window(Default::default(), |cx| {
 8807            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8808
 8809            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8810            editor.transpose(&Default::default(), cx);
 8811            assert_eq!(editor.text(cx), "bacd\ne");
 8812            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8813
 8814            editor.transpose(&Default::default(), cx);
 8815            assert_eq!(editor.text(cx), "bcade\n");
 8816            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8817
 8818            editor.transpose(&Default::default(), cx);
 8819            assert_eq!(editor.text(cx), "bcda\ne");
 8820            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8821
 8822            editor.transpose(&Default::default(), cx);
 8823            assert_eq!(editor.text(cx), "bcade\n");
 8824            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8825
 8826            editor.transpose(&Default::default(), cx);
 8827            assert_eq!(editor.text(cx), "bcaed\n");
 8828            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8829
 8830            editor
 8831        })
 8832        .1;
 8833
 8834        cx.add_window(Default::default(), |cx| {
 8835            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8836
 8837            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8838            editor.transpose(&Default::default(), cx);
 8839            assert_eq!(editor.text(cx), "🏀🍐✋");
 8840            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8841
 8842            editor.transpose(&Default::default(), cx);
 8843            assert_eq!(editor.text(cx), "🏀✋🍐");
 8844            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8845
 8846            editor.transpose(&Default::default(), cx);
 8847            assert_eq!(editor.text(cx), "🏀🍐✋");
 8848            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8849
 8850            editor
 8851        })
 8852        .1;
 8853    }
 8854
 8855    #[gpui::test]
 8856    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8857        let mut cx = EditorTestContext::new(cx).await;
 8858
 8859        cx.set_state("«one✅ ˇ»two «three ˇ»four «five ˇ»six ");
 8860        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8861        cx.assert_editor_state("ˇtwo ˇfour ˇsix ");
 8862
 8863        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8864        cx.set_state("two ˇfour ˇsix ˇ");
 8865        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8866        cx.assert_editor_state("two one✅ ˇfour three ˇsix five ˇ");
 8867
 8868        // Paste again but with only two cursors. Since the number of cursors doesn't
 8869        // match the number of slices in the clipboard, the entire clipboard text
 8870        // is pasted at each cursor.
 8871        cx.set_state("ˇtwo one✅ four three six five ˇ");
 8872        cx.update_editor(|e, cx| {
 8873            e.handle_input("( ", cx);
 8874            e.paste(&Paste, cx);
 8875            e.handle_input(") ", cx);
 8876        });
 8877        cx.assert_editor_state(indoc! {"
 8878            ( one✅ 
 8879            three 
 8880            five ) ˇtwo one✅ four three six five ( one✅ 
 8881            three 
 8882            five ) ˇ"});
 8883
 8884        // Cut with three selections, one of which is full-line.
 8885        cx.set_state(indoc! {"
 8886            1«2ˇ»3
 8887            4ˇ567
 8888            «8ˇ»9"});
 8889        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8890        cx.assert_editor_state(indoc! {"
 8891            1ˇ3
 8892            ˇ9"});
 8893
 8894        // Paste with three selections, noticing how the copied selection that was full-line
 8895        // gets inserted before the second cursor.
 8896        cx.set_state(indoc! {"
 8897            1ˇ3
 8898 8899            «oˇ»ne"});
 8900        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8901        cx.assert_editor_state(indoc! {"
 8902            12ˇ3
 8903            4567
 8904 8905            8ˇne"});
 8906
 8907        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8908        cx.set_state(indoc! {"
 8909            The quick brown
 8910            fox juˇmps over
 8911            the lazy dog"});
 8912        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8913        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8914
 8915        // Paste with three selections, noticing how the copied full-line selection is inserted
 8916        // before the empty selections but replaces the selection that is non-empty.
 8917        cx.set_state(indoc! {"
 8918            Tˇhe quick brown
 8919            «foˇ»x jumps over
 8920            tˇhe lazy dog"});
 8921        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8922        cx.assert_editor_state(indoc! {"
 8923            fox jumps over
 8924            Tˇhe quick brown
 8925            fox jumps over
 8926            ˇx jumps over
 8927            fox jumps over
 8928            tˇhe lazy dog"});
 8929    }
 8930
 8931    #[gpui::test]
 8932    async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
 8933        let mut cx = EditorTestContext::new(cx).await;
 8934        let language = Arc::new(Language::new(
 8935            LanguageConfig::default(),
 8936            Some(tree_sitter_rust::language()),
 8937        ));
 8938        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8939
 8940        // Cut an indented block, without the leading whitespace.
 8941        cx.set_state(indoc! {"
 8942            const a: B = (
 8943                c(),
 8944                «d(
 8945                    e,
 8946                    f
 8947                )ˇ»
 8948            );
 8949        "});
 8950        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8951        cx.assert_editor_state(indoc! {"
 8952            const a: B = (
 8953                c(),
 8954                ˇ
 8955            );
 8956        "});
 8957
 8958        // Paste it at the same position.
 8959        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8960        cx.assert_editor_state(indoc! {"
 8961            const a: B = (
 8962                c(),
 8963                d(
 8964                    e,
 8965                    f
 8966 8967            );
 8968        "});
 8969
 8970        // Paste it at a line with a lower indent level.
 8971        cx.set_state(indoc! {"
 8972            ˇ
 8973            const a: B = (
 8974                c(),
 8975            );
 8976        "});
 8977        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8978        cx.assert_editor_state(indoc! {"
 8979            d(
 8980                e,
 8981                f
 8982 8983            const a: B = (
 8984                c(),
 8985            );
 8986        "});
 8987
 8988        // Cut an indented block, with the leading whitespace.
 8989        cx.set_state(indoc! {"
 8990            const a: B = (
 8991                c(),
 8992            «    d(
 8993                    e,
 8994                    f
 8995                )
 8996            ˇ»);
 8997        "});
 8998        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8999        cx.assert_editor_state(indoc! {"
 9000            const a: B = (
 9001                c(),
 9002            ˇ);
 9003        "});
 9004
 9005        // Paste it at the same position.
 9006        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9007        cx.assert_editor_state(indoc! {"
 9008            const a: B = (
 9009                c(),
 9010                d(
 9011                    e,
 9012                    f
 9013                )
 9014            ˇ);
 9015        "});
 9016
 9017        // Paste it at a line with a higher indent level.
 9018        cx.set_state(indoc! {"
 9019            const a: B = (
 9020                c(),
 9021                d(
 9022                    e,
 9023 9024                )
 9025            );
 9026        "});
 9027        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9028        cx.assert_editor_state(indoc! {"
 9029            const a: B = (
 9030                c(),
 9031                d(
 9032                    e,
 9033                    f    d(
 9034                        e,
 9035                        f
 9036                    )
 9037            ˇ
 9038                )
 9039            );
 9040        "});
 9041    }
 9042
 9043    #[gpui::test]
 9044    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 9045        cx.set_global(Settings::test(cx));
 9046        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 9047        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9048        view.update(cx, |view, cx| {
 9049            view.select_all(&SelectAll, cx);
 9050            assert_eq!(
 9051                view.selections.display_ranges(cx),
 9052                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 9053            );
 9054        });
 9055    }
 9056
 9057    #[gpui::test]
 9058    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 9059        cx.set_global(Settings::test(cx));
 9060        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 9061        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9062        view.update(cx, |view, cx| {
 9063            view.change_selections(None, cx, |s| {
 9064                s.select_display_ranges([
 9065                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9066                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9067                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9068                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 9069                ])
 9070            });
 9071            view.select_line(&SelectLine, cx);
 9072            assert_eq!(
 9073                view.selections.display_ranges(cx),
 9074                vec![
 9075                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 9076                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 9077                ]
 9078            );
 9079        });
 9080
 9081        view.update(cx, |view, cx| {
 9082            view.select_line(&SelectLine, cx);
 9083            assert_eq!(
 9084                view.selections.display_ranges(cx),
 9085                vec![
 9086                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 9087                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 9088                ]
 9089            );
 9090        });
 9091
 9092        view.update(cx, |view, cx| {
 9093            view.select_line(&SelectLine, cx);
 9094            assert_eq!(
 9095                view.selections.display_ranges(cx),
 9096                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 9097            );
 9098        });
 9099    }
 9100
 9101    #[gpui::test]
 9102    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 9103        cx.set_global(Settings::test(cx));
 9104        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 9105        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9106        view.update(cx, |view, cx| {
 9107            view.fold_ranges(
 9108                vec![
 9109                    Point::new(0, 2)..Point::new(1, 2),
 9110                    Point::new(2, 3)..Point::new(4, 1),
 9111                    Point::new(7, 0)..Point::new(8, 4),
 9112                ],
 9113                cx,
 9114            );
 9115            view.change_selections(None, cx, |s| {
 9116                s.select_display_ranges([
 9117                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9118                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9119                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9120                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9121                ])
 9122            });
 9123            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 9124        });
 9125
 9126        view.update(cx, |view, cx| {
 9127            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9128            assert_eq!(
 9129                view.display_text(cx),
 9130                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 9131            );
 9132            assert_eq!(
 9133                view.selections.display_ranges(cx),
 9134                [
 9135                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 9136                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9137                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 9138                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 9139                ]
 9140            );
 9141        });
 9142
 9143        view.update(cx, |view, cx| {
 9144            view.change_selections(None, cx, |s| {
 9145                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 9146            });
 9147            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9148            assert_eq!(
 9149                view.display_text(cx),
 9150                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 9151            );
 9152            assert_eq!(
 9153                view.selections.display_ranges(cx),
 9154                [
 9155                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 9156                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 9157                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9158                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 9159                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 9160                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 9161                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 9162                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 9163                ]
 9164            );
 9165        });
 9166    }
 9167
 9168    #[gpui::test]
 9169    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 9170        cx.set_global(Settings::test(cx));
 9171        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 9172        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9173
 9174        view.update(cx, |view, cx| {
 9175            view.change_selections(None, cx, |s| {
 9176                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 9177            });
 9178        });
 9179        view.update(cx, |view, cx| {
 9180            view.add_selection_above(&AddSelectionAbove, cx);
 9181            assert_eq!(
 9182                view.selections.display_ranges(cx),
 9183                vec![
 9184                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9185                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9186                ]
 9187            );
 9188        });
 9189
 9190        view.update(cx, |view, cx| {
 9191            view.add_selection_above(&AddSelectionAbove, cx);
 9192            assert_eq!(
 9193                view.selections.display_ranges(cx),
 9194                vec![
 9195                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9196                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9197                ]
 9198            );
 9199        });
 9200
 9201        view.update(cx, |view, cx| {
 9202            view.add_selection_below(&AddSelectionBelow, cx);
 9203            assert_eq!(
 9204                view.selections.display_ranges(cx),
 9205                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9206            );
 9207
 9208            view.undo_selection(&UndoSelection, cx);
 9209            assert_eq!(
 9210                view.selections.display_ranges(cx),
 9211                vec![
 9212                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9213                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9214                ]
 9215            );
 9216
 9217            view.redo_selection(&RedoSelection, cx);
 9218            assert_eq!(
 9219                view.selections.display_ranges(cx),
 9220                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9221            );
 9222        });
 9223
 9224        view.update(cx, |view, cx| {
 9225            view.add_selection_below(&AddSelectionBelow, cx);
 9226            assert_eq!(
 9227                view.selections.display_ranges(cx),
 9228                vec![
 9229                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9230                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9231                ]
 9232            );
 9233        });
 9234
 9235        view.update(cx, |view, cx| {
 9236            view.add_selection_below(&AddSelectionBelow, cx);
 9237            assert_eq!(
 9238                view.selections.display_ranges(cx),
 9239                vec![
 9240                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9241                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9242                ]
 9243            );
 9244        });
 9245
 9246        view.update(cx, |view, cx| {
 9247            view.change_selections(None, cx, |s| {
 9248                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 9249            });
 9250        });
 9251        view.update(cx, |view, cx| {
 9252            view.add_selection_below(&AddSelectionBelow, cx);
 9253            assert_eq!(
 9254                view.selections.display_ranges(cx),
 9255                vec![
 9256                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9257                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9258                ]
 9259            );
 9260        });
 9261
 9262        view.update(cx, |view, cx| {
 9263            view.add_selection_below(&AddSelectionBelow, cx);
 9264            assert_eq!(
 9265                view.selections.display_ranges(cx),
 9266                vec![
 9267                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9268                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9269                ]
 9270            );
 9271        });
 9272
 9273        view.update(cx, |view, cx| {
 9274            view.add_selection_above(&AddSelectionAbove, cx);
 9275            assert_eq!(
 9276                view.selections.display_ranges(cx),
 9277                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9278            );
 9279        });
 9280
 9281        view.update(cx, |view, cx| {
 9282            view.add_selection_above(&AddSelectionAbove, cx);
 9283            assert_eq!(
 9284                view.selections.display_ranges(cx),
 9285                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9286            );
 9287        });
 9288
 9289        view.update(cx, |view, cx| {
 9290            view.change_selections(None, cx, |s| {
 9291                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 9292            });
 9293            view.add_selection_below(&AddSelectionBelow, cx);
 9294            assert_eq!(
 9295                view.selections.display_ranges(cx),
 9296                vec![
 9297                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9298                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9299                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9300                ]
 9301            );
 9302        });
 9303
 9304        view.update(cx, |view, cx| {
 9305            view.add_selection_below(&AddSelectionBelow, cx);
 9306            assert_eq!(
 9307                view.selections.display_ranges(cx),
 9308                vec![
 9309                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9310                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9311                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9312                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 9313                ]
 9314            );
 9315        });
 9316
 9317        view.update(cx, |view, cx| {
 9318            view.add_selection_above(&AddSelectionAbove, cx);
 9319            assert_eq!(
 9320                view.selections.display_ranges(cx),
 9321                vec![
 9322                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9323                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9324                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9325                ]
 9326            );
 9327        });
 9328
 9329        view.update(cx, |view, cx| {
 9330            view.change_selections(None, cx, |s| {
 9331                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 9332            });
 9333        });
 9334        view.update(cx, |view, cx| {
 9335            view.add_selection_above(&AddSelectionAbove, cx);
 9336            assert_eq!(
 9337                view.selections.display_ranges(cx),
 9338                vec![
 9339                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 9340                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9341                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9342                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9343                ]
 9344            );
 9345        });
 9346
 9347        view.update(cx, |view, cx| {
 9348            view.add_selection_below(&AddSelectionBelow, cx);
 9349            assert_eq!(
 9350                view.selections.display_ranges(cx),
 9351                vec![
 9352                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9353                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9354                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9355                ]
 9356            );
 9357        });
 9358    }
 9359
 9360    #[gpui::test]
 9361    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 9362        cx.set_global(Settings::test(cx));
 9363
 9364        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 9365        let buffer = MultiBuffer::build_simple(&text, cx);
 9366        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9367
 9368        view.update(cx, |view, cx| {
 9369            view.change_selections(None, cx, |s| {
 9370                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 9371            });
 9372            view.select_next(
 9373                &SelectNext {
 9374                    replace_newest: false,
 9375                },
 9376                cx,
 9377            );
 9378            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 9379
 9380            view.select_next(
 9381                &SelectNext {
 9382                    replace_newest: false,
 9383                },
 9384                cx,
 9385            );
 9386            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 9387
 9388            view.undo_selection(&UndoSelection, cx);
 9389            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 9390
 9391            view.redo_selection(&RedoSelection, cx);
 9392            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 9393
 9394            view.select_next(
 9395                &SelectNext {
 9396                    replace_newest: false,
 9397                },
 9398                cx,
 9399            );
 9400            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 9401
 9402            view.select_next(
 9403                &SelectNext {
 9404                    replace_newest: false,
 9405                },
 9406                cx,
 9407            );
 9408            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 9409        });
 9410    }
 9411
 9412    #[gpui::test]
 9413    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 9414        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9415        let language = Arc::new(Language::new(
 9416            LanguageConfig::default(),
 9417            Some(tree_sitter_rust::language()),
 9418        ));
 9419
 9420        let text = r#"
 9421            use mod1::mod2::{mod3, mod4};
 9422
 9423            fn fn_1(param1: bool, param2: &str) {
 9424                let var1 = "text";
 9425            }
 9426        "#
 9427        .unindent();
 9428
 9429        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9430        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9431        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9432        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9433            .await;
 9434
 9435        view.update(cx, |view, cx| {
 9436            view.change_selections(None, cx, |s| {
 9437                s.select_display_ranges([
 9438                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9439                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9440                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9441                ]);
 9442            });
 9443            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9444        });
 9445        assert_eq!(
 9446            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 9447            &[
 9448                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9449                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9450                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9451            ]
 9452        );
 9453
 9454        view.update(cx, |view, cx| {
 9455            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9456        });
 9457        assert_eq!(
 9458            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9459            &[
 9460                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9461                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9462            ]
 9463        );
 9464
 9465        view.update(cx, |view, cx| {
 9466            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9467        });
 9468        assert_eq!(
 9469            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9470            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9471        );
 9472
 9473        // Trying to expand the selected syntax node one more time has no effect.
 9474        view.update(cx, |view, cx| {
 9475            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9476        });
 9477        assert_eq!(
 9478            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9479            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9480        );
 9481
 9482        view.update(cx, |view, cx| {
 9483            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9484        });
 9485        assert_eq!(
 9486            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9487            &[
 9488                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9489                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9490            ]
 9491        );
 9492
 9493        view.update(cx, |view, cx| {
 9494            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9495        });
 9496        assert_eq!(
 9497            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9498            &[
 9499                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9500                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9501                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9502            ]
 9503        );
 9504
 9505        view.update(cx, |view, cx| {
 9506            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9507        });
 9508        assert_eq!(
 9509            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9510            &[
 9511                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9512                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9513                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9514            ]
 9515        );
 9516
 9517        // Trying to shrink the selected syntax node one more time has no effect.
 9518        view.update(cx, |view, cx| {
 9519            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9520        });
 9521        assert_eq!(
 9522            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9523            &[
 9524                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9525                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9526                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9527            ]
 9528        );
 9529
 9530        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9531        // a fold.
 9532        view.update(cx, |view, cx| {
 9533            view.fold_ranges(
 9534                vec![
 9535                    Point::new(0, 21)..Point::new(0, 24),
 9536                    Point::new(3, 20)..Point::new(3, 22),
 9537                ],
 9538                cx,
 9539            );
 9540            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9541        });
 9542        assert_eq!(
 9543            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9544            &[
 9545                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9546                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9547                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9548            ]
 9549        );
 9550    }
 9551
 9552    #[gpui::test]
 9553    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9554        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9555        let language = Arc::new(
 9556            Language::new(
 9557                LanguageConfig {
 9558                    brackets: vec![
 9559                        BracketPair {
 9560                            start: "{".to_string(),
 9561                            end: "}".to_string(),
 9562                            close: false,
 9563                            newline: true,
 9564                        },
 9565                        BracketPair {
 9566                            start: "(".to_string(),
 9567                            end: ")".to_string(),
 9568                            close: false,
 9569                            newline: true,
 9570                        },
 9571                    ],
 9572                    ..Default::default()
 9573                },
 9574                Some(tree_sitter_rust::language()),
 9575            )
 9576            .with_indents_query(
 9577                r#"
 9578                (_ "(" ")" @end) @indent
 9579                (_ "{" "}" @end) @indent
 9580                "#,
 9581            )
 9582            .unwrap(),
 9583        );
 9584
 9585        let text = "fn a() {}";
 9586
 9587        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9588        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9589        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9590        editor
 9591            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9592            .await;
 9593
 9594        editor.update(cx, |editor, cx| {
 9595            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 9596            editor.newline(&Newline, cx);
 9597            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9598            assert_eq!(
 9599                editor.selections.ranges(cx),
 9600                &[
 9601                    Point::new(1, 4)..Point::new(1, 4),
 9602                    Point::new(3, 4)..Point::new(3, 4),
 9603                    Point::new(5, 0)..Point::new(5, 0)
 9604                ]
 9605            );
 9606        });
 9607    }
 9608
 9609    #[gpui::test]
 9610    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9611        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9612        let language = Arc::new(Language::new(
 9613            LanguageConfig {
 9614                brackets: vec![
 9615                    BracketPair {
 9616                        start: "{".to_string(),
 9617                        end: "}".to_string(),
 9618                        close: true,
 9619                        newline: true,
 9620                    },
 9621                    BracketPair {
 9622                        start: "/*".to_string(),
 9623                        end: " */".to_string(),
 9624                        close: true,
 9625                        newline: true,
 9626                    },
 9627                    BracketPair {
 9628                        start: "[".to_string(),
 9629                        end: "]".to_string(),
 9630                        close: false,
 9631                        newline: true,
 9632                    },
 9633                ],
 9634                autoclose_before: "})]".to_string(),
 9635                ..Default::default()
 9636            },
 9637            Some(tree_sitter_rust::language()),
 9638        ));
 9639
 9640        let text = r#"
 9641            a
 9642
 9643            /
 9644
 9645        "#
 9646        .unindent();
 9647
 9648        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9649        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9650        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9651        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9652            .await;
 9653
 9654        view.update(cx, |view, cx| {
 9655            view.change_selections(None, cx, |s| {
 9656                s.select_display_ranges([
 9657                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9658                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9659                ])
 9660            });
 9661
 9662            view.handle_input("{", cx);
 9663            view.handle_input("{", cx);
 9664            view.handle_input("{", cx);
 9665            assert_eq!(
 9666                view.text(cx),
 9667                "
 9668                {{{}}}
 9669                {{{}}}
 9670                /
 9671
 9672                "
 9673                .unindent()
 9674            );
 9675
 9676            view.move_right(&MoveRight, cx);
 9677            view.handle_input("}", cx);
 9678            view.handle_input("}", cx);
 9679            view.handle_input("}", cx);
 9680            assert_eq!(
 9681                view.text(cx),
 9682                "
 9683                {{{}}}}
 9684                {{{}}}}
 9685                /
 9686
 9687                "
 9688                .unindent()
 9689            );
 9690
 9691            view.undo(&Undo, cx);
 9692            view.handle_input("/", cx);
 9693            view.handle_input("*", cx);
 9694            assert_eq!(
 9695                view.text(cx),
 9696                "
 9697                /* */
 9698                /* */
 9699                /
 9700
 9701                "
 9702                .unindent()
 9703            );
 9704
 9705            view.undo(&Undo, cx);
 9706            view.change_selections(None, cx, |s| {
 9707                s.select_display_ranges([
 9708                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9709                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9710                ])
 9711            });
 9712            view.handle_input("*", cx);
 9713            assert_eq!(
 9714                view.text(cx),
 9715                "
 9716                a
 9717
 9718                /*
 9719                *
 9720                "
 9721                .unindent()
 9722            );
 9723
 9724            // Don't autoclose if the next character isn't whitespace and isn't
 9725            // listed in the language's "autoclose_before" section.
 9726            view.finalize_last_transaction(cx);
 9727            view.change_selections(None, cx, |s| {
 9728                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 9729            });
 9730            view.handle_input("{", cx);
 9731            assert_eq!(
 9732                view.text(cx),
 9733                "
 9734                {a
 9735
 9736                /*
 9737                *
 9738                "
 9739                .unindent()
 9740            );
 9741
 9742            view.undo(&Undo, cx);
 9743            view.change_selections(None, cx, |s| {
 9744                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 9745            });
 9746            view.handle_input("{", cx);
 9747            assert_eq!(
 9748                view.text(cx),
 9749                "
 9750                {a}
 9751
 9752                /*
 9753                *
 9754                "
 9755                .unindent()
 9756            );
 9757            assert_eq!(
 9758                view.selections.display_ranges(cx),
 9759                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9760            );
 9761
 9762            view.undo(&Undo, cx);
 9763            view.handle_input("[", cx);
 9764            assert_eq!(
 9765                view.text(cx),
 9766                "
 9767                [a]
 9768                
 9769                /*
 9770                *
 9771                "
 9772                .unindent()
 9773            );
 9774            assert_eq!(
 9775                view.selections.display_ranges(cx),
 9776                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9777            );
 9778
 9779            view.undo(&Undo, cx);
 9780            view.change_selections(None, cx, |s| {
 9781                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9782            });
 9783            view.handle_input("[", cx);
 9784            assert_eq!(
 9785                view.text(cx),
 9786                "
 9787                a[
 9788                
 9789                /*
 9790                *
 9791                "
 9792                .unindent()
 9793            );
 9794            assert_eq!(
 9795                view.selections.display_ranges(cx),
 9796                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9797            );
 9798        });
 9799    }
 9800
 9801    #[gpui::test]
 9802    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9803        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9804        let language = Arc::new(Language::new(
 9805            LanguageConfig {
 9806                brackets: vec![BracketPair {
 9807                    start: "{".to_string(),
 9808                    end: "}".to_string(),
 9809                    close: true,
 9810                    newline: true,
 9811                }],
 9812                ..Default::default()
 9813            },
 9814            Some(tree_sitter_rust::language()),
 9815        ));
 9816
 9817        let text = r#"
 9818            a
 9819            b
 9820            c
 9821        "#
 9822        .unindent();
 9823
 9824        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9825        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9826        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9827        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9828            .await;
 9829
 9830        view.update(cx, |view, cx| {
 9831            view.change_selections(None, cx, |s| {
 9832                s.select_display_ranges([
 9833                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9834                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9835                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9836                ])
 9837            });
 9838
 9839            view.handle_input("{", cx);
 9840            view.handle_input("{", cx);
 9841            view.handle_input("{", cx);
 9842            assert_eq!(
 9843                view.text(cx),
 9844                "
 9845                {{{a}}}
 9846                {{{b}}}
 9847                {{{c}}}
 9848                "
 9849                .unindent()
 9850            );
 9851            assert_eq!(
 9852                view.selections.display_ranges(cx),
 9853                [
 9854                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9855                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9856                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9857                ]
 9858            );
 9859
 9860            view.undo(&Undo, cx);
 9861            assert_eq!(
 9862                view.text(cx),
 9863                "
 9864                a
 9865                b
 9866                c
 9867                "
 9868                .unindent()
 9869            );
 9870            assert_eq!(
 9871                view.selections.display_ranges(cx),
 9872                [
 9873                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9874                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9875                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9876                ]
 9877            );
 9878        });
 9879    }
 9880
 9881    #[gpui::test]
 9882    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9883        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9884        let language = Arc::new(Language::new(
 9885            LanguageConfig {
 9886                brackets: vec![BracketPair {
 9887                    start: "{".to_string(),
 9888                    end: "}".to_string(),
 9889                    close: true,
 9890                    newline: true,
 9891                }],
 9892                autoclose_before: "}".to_string(),
 9893                ..Default::default()
 9894            },
 9895            Some(tree_sitter_rust::language()),
 9896        ));
 9897
 9898        let text = r#"
 9899            a
 9900            b
 9901            c
 9902        "#
 9903        .unindent();
 9904
 9905        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9906        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9907        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9908        editor
 9909            .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9910            .await;
 9911
 9912        editor.update(cx, |editor, cx| {
 9913            editor.change_selections(None, cx, |s| {
 9914                s.select_ranges([
 9915                    Point::new(0, 1)..Point::new(0, 1),
 9916                    Point::new(1, 1)..Point::new(1, 1),
 9917                    Point::new(2, 1)..Point::new(2, 1),
 9918                ])
 9919            });
 9920
 9921            editor.handle_input("{", cx);
 9922            editor.handle_input("{", cx);
 9923            editor.handle_input("_", cx);
 9924            assert_eq!(
 9925                editor.text(cx),
 9926                "
 9927                a{{_}}
 9928                b{{_}}
 9929                c{{_}}
 9930                "
 9931                .unindent()
 9932            );
 9933            assert_eq!(
 9934                editor.selections.ranges::<Point>(cx),
 9935                [
 9936                    Point::new(0, 4)..Point::new(0, 4),
 9937                    Point::new(1, 4)..Point::new(1, 4),
 9938                    Point::new(2, 4)..Point::new(2, 4)
 9939                ]
 9940            );
 9941
 9942            editor.backspace(&Default::default(), cx);
 9943            editor.backspace(&Default::default(), cx);
 9944            assert_eq!(
 9945                editor.text(cx),
 9946                "
 9947                a{}
 9948                b{}
 9949                c{}
 9950                "
 9951                .unindent()
 9952            );
 9953            assert_eq!(
 9954                editor.selections.ranges::<Point>(cx),
 9955                [
 9956                    Point::new(0, 2)..Point::new(0, 2),
 9957                    Point::new(1, 2)..Point::new(1, 2),
 9958                    Point::new(2, 2)..Point::new(2, 2)
 9959                ]
 9960            );
 9961
 9962            editor.delete_to_previous_word_start(&Default::default(), cx);
 9963            assert_eq!(
 9964                editor.text(cx),
 9965                "
 9966                a
 9967                b
 9968                c
 9969                "
 9970                .unindent()
 9971            );
 9972            assert_eq!(
 9973                editor.selections.ranges::<Point>(cx),
 9974                [
 9975                    Point::new(0, 1)..Point::new(0, 1),
 9976                    Point::new(1, 1)..Point::new(1, 1),
 9977                    Point::new(2, 1)..Point::new(2, 1)
 9978                ]
 9979            );
 9980        });
 9981    }
 9982
 9983    #[gpui::test]
 9984    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9985        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9986
 9987        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 9988            a.| b
 9989            a.| b
 9990            a.| b"});
 9991        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9992        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9993
 9994        editor.update(cx, |editor, cx| {
 9995            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9996
 9997            editor
 9998                .insert_snippet(&insertion_ranges, snippet, cx)
 9999                .unwrap();
10000
10001            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
10002                let range_markers = ('<', '>');
10003                let (expected_text, mut selection_ranges_lookup) =
10004                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
10005                let selection_ranges = selection_ranges_lookup
10006                    .remove(&range_markers.into())
10007                    .unwrap();
10008                assert_eq!(editor.text(cx), expected_text);
10009                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
10010            }
10011            assert(
10012                editor,
10013                cx,
10014                indoc! {"
10015                    a.f(<one>, two, <three>) b
10016                    a.f(<one>, two, <three>) b
10017                    a.f(<one>, two, <three>) b"},
10018            );
10019
10020            // Can't move earlier than the first tab stop
10021            assert!(!editor.move_to_prev_snippet_tabstop(cx));
10022            assert(
10023                editor,
10024                cx,
10025                indoc! {"
10026                    a.f(<one>, two, <three>) b
10027                    a.f(<one>, two, <three>) b
10028                    a.f(<one>, two, <three>) b"},
10029            );
10030
10031            assert!(editor.move_to_next_snippet_tabstop(cx));
10032            assert(
10033                editor,
10034                cx,
10035                indoc! {"
10036                    a.f(one, <two>, three) b
10037                    a.f(one, <two>, three) b
10038                    a.f(one, <two>, three) b"},
10039            );
10040
10041            editor.move_to_prev_snippet_tabstop(cx);
10042            assert(
10043                editor,
10044                cx,
10045                indoc! {"
10046                    a.f(<one>, two, <three>) b
10047                    a.f(<one>, two, <three>) b
10048                    a.f(<one>, two, <three>) b"},
10049            );
10050
10051            assert!(editor.move_to_next_snippet_tabstop(cx));
10052            assert(
10053                editor,
10054                cx,
10055                indoc! {"
10056                    a.f(one, <two>, three) b
10057                    a.f(one, <two>, three) b
10058                    a.f(one, <two>, three) b"},
10059            );
10060            assert!(editor.move_to_next_snippet_tabstop(cx));
10061            assert(
10062                editor,
10063                cx,
10064                indoc! {"
10065                    a.f(one, two, three)<> b
10066                    a.f(one, two, three)<> b
10067                    a.f(one, two, three)<> b"},
10068            );
10069
10070            // As soon as the last tab stop is reached, snippet state is gone
10071            editor.move_to_prev_snippet_tabstop(cx);
10072            assert(
10073                editor,
10074                cx,
10075                indoc! {"
10076                    a.f(one, two, three)<> b
10077                    a.f(one, two, three)<> b
10078                    a.f(one, two, three)<> b"},
10079            );
10080        });
10081    }
10082
10083    #[gpui::test]
10084    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
10085        cx.foreground().forbid_parking();
10086
10087        let mut language = Language::new(
10088            LanguageConfig {
10089                name: "Rust".into(),
10090                path_suffixes: vec!["rs".to_string()],
10091                ..Default::default()
10092            },
10093            Some(tree_sitter_rust::language()),
10094        );
10095        let mut fake_servers = language
10096            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10097                capabilities: lsp::ServerCapabilities {
10098                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
10099                    ..Default::default()
10100                },
10101                ..Default::default()
10102            }))
10103            .await;
10104
10105        let fs = FakeFs::new(cx.background().clone());
10106        fs.insert_file("/file.rs", Default::default()).await;
10107
10108        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10109        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10110        let buffer = project
10111            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10112            .await
10113            .unwrap();
10114
10115        cx.foreground().start_waiting();
10116        let fake_server = fake_servers.next().await.unwrap();
10117
10118        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10119        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10120        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10121        assert!(cx.read(|cx| editor.is_dirty(cx)));
10122
10123        let save = cx.update(|cx| editor.save(project.clone(), cx));
10124        fake_server
10125            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10126                assert_eq!(
10127                    params.text_document.uri,
10128                    lsp::Url::from_file_path("/file.rs").unwrap()
10129                );
10130                assert_eq!(params.options.tab_size, 4);
10131                Ok(Some(vec![lsp::TextEdit::new(
10132                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10133                    ", ".to_string(),
10134                )]))
10135            })
10136            .next()
10137            .await;
10138        cx.foreground().start_waiting();
10139        save.await.unwrap();
10140        assert_eq!(
10141            editor.read_with(cx, |editor, cx| editor.text(cx)),
10142            "one, two\nthree\n"
10143        );
10144        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10145
10146        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10147        assert!(cx.read(|cx| editor.is_dirty(cx)));
10148
10149        // Ensure we can still save even if formatting hangs.
10150        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10151            assert_eq!(
10152                params.text_document.uri,
10153                lsp::Url::from_file_path("/file.rs").unwrap()
10154            );
10155            futures::future::pending::<()>().await;
10156            unreachable!()
10157        });
10158        let save = cx.update(|cx| editor.save(project.clone(), cx));
10159        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10160        cx.foreground().start_waiting();
10161        save.await.unwrap();
10162        assert_eq!(
10163            editor.read_with(cx, |editor, cx| editor.text(cx)),
10164            "one\ntwo\nthree\n"
10165        );
10166        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10167
10168        // Set rust language override and assert overriden tabsize is sent to language server
10169        cx.update(|cx| {
10170            cx.update_global::<Settings, _, _>(|settings, _| {
10171                settings.language_overrides.insert(
10172                    "Rust".into(),
10173                    EditorSettings {
10174                        tab_size: Some(8.try_into().unwrap()),
10175                        ..Default::default()
10176                    },
10177                );
10178            })
10179        });
10180
10181        let save = cx.update(|cx| editor.save(project.clone(), cx));
10182        fake_server
10183            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10184                assert_eq!(
10185                    params.text_document.uri,
10186                    lsp::Url::from_file_path("/file.rs").unwrap()
10187                );
10188                assert_eq!(params.options.tab_size, 8);
10189                Ok(Some(vec![]))
10190            })
10191            .next()
10192            .await;
10193        cx.foreground().start_waiting();
10194        save.await.unwrap();
10195    }
10196
10197    #[gpui::test]
10198    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
10199        cx.foreground().forbid_parking();
10200
10201        let mut language = Language::new(
10202            LanguageConfig {
10203                name: "Rust".into(),
10204                path_suffixes: vec!["rs".to_string()],
10205                ..Default::default()
10206            },
10207            Some(tree_sitter_rust::language()),
10208        );
10209        let mut fake_servers = language
10210            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10211                capabilities: lsp::ServerCapabilities {
10212                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
10213                    ..Default::default()
10214                },
10215                ..Default::default()
10216            }))
10217            .await;
10218
10219        let fs = FakeFs::new(cx.background().clone());
10220        fs.insert_file("/file.rs", Default::default()).await;
10221
10222        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10223        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10224        let buffer = project
10225            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10226            .await
10227            .unwrap();
10228
10229        cx.foreground().start_waiting();
10230        let fake_server = fake_servers.next().await.unwrap();
10231
10232        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10233        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10234        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10235        assert!(cx.read(|cx| editor.is_dirty(cx)));
10236
10237        let save = cx.update(|cx| editor.save(project.clone(), cx));
10238        fake_server
10239            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10240                assert_eq!(
10241                    params.text_document.uri,
10242                    lsp::Url::from_file_path("/file.rs").unwrap()
10243                );
10244                assert_eq!(params.options.tab_size, 4);
10245                Ok(Some(vec![lsp::TextEdit::new(
10246                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10247                    ", ".to_string(),
10248                )]))
10249            })
10250            .next()
10251            .await;
10252        cx.foreground().start_waiting();
10253        save.await.unwrap();
10254        assert_eq!(
10255            editor.read_with(cx, |editor, cx| editor.text(cx)),
10256            "one, two\nthree\n"
10257        );
10258        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10259
10260        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10261        assert!(cx.read(|cx| editor.is_dirty(cx)));
10262
10263        // Ensure we can still save even if formatting hangs.
10264        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
10265            move |params, _| async move {
10266                assert_eq!(
10267                    params.text_document.uri,
10268                    lsp::Url::from_file_path("/file.rs").unwrap()
10269                );
10270                futures::future::pending::<()>().await;
10271                unreachable!()
10272            },
10273        );
10274        let save = cx.update(|cx| editor.save(project.clone(), cx));
10275        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10276        cx.foreground().start_waiting();
10277        save.await.unwrap();
10278        assert_eq!(
10279            editor.read_with(cx, |editor, cx| editor.text(cx)),
10280            "one\ntwo\nthree\n"
10281        );
10282        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10283
10284        // Set rust language override and assert overriden tabsize is sent to language server
10285        cx.update(|cx| {
10286            cx.update_global::<Settings, _, _>(|settings, _| {
10287                settings.language_overrides.insert(
10288                    "Rust".into(),
10289                    EditorSettings {
10290                        tab_size: Some(8.try_into().unwrap()),
10291                        ..Default::default()
10292                    },
10293                );
10294            })
10295        });
10296
10297        let save = cx.update(|cx| editor.save(project.clone(), cx));
10298        fake_server
10299            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10300                assert_eq!(
10301                    params.text_document.uri,
10302                    lsp::Url::from_file_path("/file.rs").unwrap()
10303                );
10304                assert_eq!(params.options.tab_size, 8);
10305                Ok(Some(vec![]))
10306            })
10307            .next()
10308            .await;
10309        cx.foreground().start_waiting();
10310        save.await.unwrap();
10311    }
10312
10313    #[gpui::test]
10314    async fn test_completion(cx: &mut gpui::TestAppContext) {
10315        let mut cx = EditorLspTestContext::new_rust(
10316            lsp::ServerCapabilities {
10317                completion_provider: Some(lsp::CompletionOptions {
10318                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
10319                    ..Default::default()
10320                }),
10321                ..Default::default()
10322            },
10323            cx,
10324        )
10325        .await;
10326
10327        cx.set_state(indoc! {"
10328            oneˇ
10329            two
10330            three
10331        "});
10332        cx.simulate_keystroke(".");
10333        handle_completion_request(
10334            &mut cx,
10335            indoc! {"
10336                one.|<>
10337                two
10338                three
10339            "},
10340            vec!["first_completion", "second_completion"],
10341        )
10342        .await;
10343        cx.condition(|editor, _| editor.context_menu_visible())
10344            .await;
10345        let apply_additional_edits = cx.update_editor(|editor, cx| {
10346            editor.move_down(&MoveDown, cx);
10347            editor
10348                .confirm_completion(&ConfirmCompletion::default(), cx)
10349                .unwrap()
10350        });
10351        cx.assert_editor_state(indoc! {"
10352            one.second_completionˇ
10353            two
10354            three
10355        "});
10356
10357        handle_resolve_completion_request(
10358            &mut cx,
10359            Some((
10360                indoc! {"
10361                    one.second_completion
10362                    two
10363                    three<>
10364                "},
10365                "\nadditional edit",
10366            )),
10367        )
10368        .await;
10369        apply_additional_edits.await.unwrap();
10370        cx.assert_editor_state(indoc! {"
10371            one.second_completionˇ
10372            two
10373            three
10374            additional edit
10375        "});
10376
10377        cx.set_state(indoc! {"
10378            one.second_completion
10379            twoˇ
10380            threeˇ
10381            additional edit
10382        "});
10383        cx.simulate_keystroke(" ");
10384        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10385        cx.simulate_keystroke("s");
10386        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10387
10388        cx.assert_editor_state(indoc! {"
10389            one.second_completion
10390            two sˇ
10391            three sˇ
10392            additional edit
10393        "});
10394        handle_completion_request(
10395            &mut cx,
10396            indoc! {"
10397                one.second_completion
10398                two s
10399                three <s|>
10400                additional edit
10401            "},
10402            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10403        )
10404        .await;
10405        cx.condition(|editor, _| editor.context_menu_visible())
10406            .await;
10407
10408        cx.simulate_keystroke("i");
10409
10410        handle_completion_request(
10411            &mut cx,
10412            indoc! {"
10413                one.second_completion
10414                two si
10415                three <si|>
10416                additional edit
10417            "},
10418            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10419        )
10420        .await;
10421        cx.condition(|editor, _| editor.context_menu_visible())
10422            .await;
10423
10424        let apply_additional_edits = cx.update_editor(|editor, cx| {
10425            editor
10426                .confirm_completion(&ConfirmCompletion::default(), cx)
10427                .unwrap()
10428        });
10429        cx.assert_editor_state(indoc! {"
10430            one.second_completion
10431            two sixth_completionˇ
10432            three sixth_completionˇ
10433            additional edit
10434        "});
10435
10436        handle_resolve_completion_request(&mut cx, None).await;
10437        apply_additional_edits.await.unwrap();
10438
10439        cx.update(|cx| {
10440            cx.update_global::<Settings, _, _>(|settings, _| {
10441                settings.show_completions_on_input = false;
10442            })
10443        });
10444        cx.set_state("editorˇ");
10445        cx.simulate_keystroke(".");
10446        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10447        cx.simulate_keystroke("c");
10448        cx.simulate_keystroke("l");
10449        cx.simulate_keystroke("o");
10450        cx.assert_editor_state("editor.cloˇ");
10451        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10452        cx.update_editor(|editor, cx| {
10453            editor.show_completions(&ShowCompletions, cx);
10454        });
10455        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
10456        cx.condition(|editor, _| editor.context_menu_visible())
10457            .await;
10458        let apply_additional_edits = cx.update_editor(|editor, cx| {
10459            editor
10460                .confirm_completion(&ConfirmCompletion::default(), cx)
10461                .unwrap()
10462        });
10463        cx.assert_editor_state("editor.closeˇ");
10464        handle_resolve_completion_request(&mut cx, None).await;
10465        apply_additional_edits.await.unwrap();
10466
10467        // Handle completion request passing a marked string specifying where the completion
10468        // should be triggered from using '|' character, what range should be replaced, and what completions
10469        // should be returned using '<' and '>' to delimit the range
10470        async fn handle_completion_request<'a>(
10471            cx: &mut EditorLspTestContext<'a>,
10472            marked_string: &str,
10473            completions: Vec<&'static str>,
10474        ) {
10475            let complete_from_marker: TextRangeMarker = '|'.into();
10476            let replace_range_marker: TextRangeMarker = ('<', '>').into();
10477            let (_, mut marked_ranges) = marked_text_ranges_by(
10478                marked_string,
10479                vec![complete_from_marker.clone(), replace_range_marker.clone()],
10480            );
10481
10482            let complete_from_position =
10483                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
10484            let replace_range =
10485                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10486
10487            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
10488                let completions = completions.clone();
10489                async move {
10490                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
10491                    assert_eq!(
10492                        params.text_document_position.position,
10493                        complete_from_position
10494                    );
10495                    Ok(Some(lsp::CompletionResponse::Array(
10496                        completions
10497                            .iter()
10498                            .map(|completion_text| lsp::CompletionItem {
10499                                label: completion_text.to_string(),
10500                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
10501                                    range: replace_range.clone(),
10502                                    new_text: completion_text.to_string(),
10503                                })),
10504                                ..Default::default()
10505                            })
10506                            .collect(),
10507                    )))
10508                }
10509            })
10510            .next()
10511            .await;
10512        }
10513
10514        async fn handle_resolve_completion_request<'a>(
10515            cx: &mut EditorLspTestContext<'a>,
10516            edit: Option<(&'static str, &'static str)>,
10517        ) {
10518            let edit = edit.map(|(marked_string, new_text)| {
10519                let replace_range_marker: TextRangeMarker = ('<', '>').into();
10520                let (_, mut marked_ranges) =
10521                    marked_text_ranges_by(marked_string, vec![replace_range_marker.clone()]);
10522
10523                let replace_range = cx
10524                    .to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10525
10526                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
10527            });
10528
10529            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
10530                let edit = edit.clone();
10531                async move {
10532                    Ok(lsp::CompletionItem {
10533                        additional_text_edits: edit,
10534                        ..Default::default()
10535                    })
10536                }
10537            })
10538            .next()
10539            .await;
10540        }
10541    }
10542
10543    #[gpui::test]
10544    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
10545        cx.update(|cx| cx.set_global(Settings::test(cx)));
10546        let language = Arc::new(Language::new(
10547            LanguageConfig {
10548                line_comment: Some("// ".to_string()),
10549                ..Default::default()
10550            },
10551            Some(tree_sitter_rust::language()),
10552        ));
10553
10554        let text = "
10555            fn a() {
10556                //b();
10557                // c();
10558                //  d();
10559            }
10560        "
10561        .unindent();
10562
10563        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10564        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10565        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10566
10567        view.update(cx, |editor, cx| {
10568            // If multiple selections intersect a line, the line is only
10569            // toggled once.
10570            editor.change_selections(None, cx, |s| {
10571                s.select_display_ranges([
10572                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
10573                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
10574                ])
10575            });
10576            editor.toggle_comments(&ToggleComments, cx);
10577            assert_eq!(
10578                editor.text(cx),
10579                "
10580                    fn a() {
10581                        b();
10582                        c();
10583                         d();
10584                    }
10585                "
10586                .unindent()
10587            );
10588
10589            // The comment prefix is inserted at the same column for every line
10590            // in a selection.
10591            editor.change_selections(None, cx, |s| {
10592                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
10593            });
10594            editor.toggle_comments(&ToggleComments, cx);
10595            assert_eq!(
10596                editor.text(cx),
10597                "
10598                    fn a() {
10599                        // b();
10600                        // c();
10601                        //  d();
10602                    }
10603                "
10604                .unindent()
10605            );
10606
10607            // If a selection ends at the beginning of a line, that line is not toggled.
10608            editor.change_selections(None, cx, |s| {
10609                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
10610            });
10611            editor.toggle_comments(&ToggleComments, cx);
10612            assert_eq!(
10613                editor.text(cx),
10614                "
10615                        fn a() {
10616                            // b();
10617                            c();
10618                            //  d();
10619                        }
10620                    "
10621                .unindent()
10622            );
10623        });
10624    }
10625
10626    #[gpui::test]
10627    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
10628        cx.set_global(Settings::test(cx));
10629        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10630        let multibuffer = cx.add_model(|cx| {
10631            let mut multibuffer = MultiBuffer::new(0);
10632            multibuffer.push_excerpts(
10633                buffer.clone(),
10634                [
10635                    ExcerptRange {
10636                        context: Point::new(0, 0)..Point::new(0, 4),
10637                        primary: None,
10638                    },
10639                    ExcerptRange {
10640                        context: Point::new(1, 0)..Point::new(1, 4),
10641                        primary: None,
10642                    },
10643                ],
10644                cx,
10645            );
10646            multibuffer
10647        });
10648
10649        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
10650
10651        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10652        view.update(cx, |view, cx| {
10653            assert_eq!(view.text(cx), "aaaa\nbbbb");
10654            view.change_selections(None, cx, |s| {
10655                s.select_ranges([
10656                    Point::new(0, 0)..Point::new(0, 0),
10657                    Point::new(1, 0)..Point::new(1, 0),
10658                ])
10659            });
10660
10661            view.handle_input("X", cx);
10662            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
10663            assert_eq!(
10664                view.selections.ranges(cx),
10665                [
10666                    Point::new(0, 1)..Point::new(0, 1),
10667                    Point::new(1, 1)..Point::new(1, 1),
10668                ]
10669            )
10670        });
10671    }
10672
10673    #[gpui::test]
10674    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
10675        cx.set_global(Settings::test(cx));
10676        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
10677                [aaaa
10678                (bbbb]
10679                cccc)"});
10680        let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
10681            context,
10682            primary: None,
10683        });
10684        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
10685        let multibuffer = cx.add_model(|cx| {
10686            let mut multibuffer = MultiBuffer::new(0);
10687            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
10688            multibuffer
10689        });
10690
10691        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10692        view.update(cx, |view, cx| {
10693            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
10694                aaaa
10695                b|bbb
10696                b|bb|b
10697                cccc"});
10698            assert_eq!(view.text(cx), expected_text);
10699            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
10700
10701            view.handle_input("X", cx);
10702
10703            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10704                aaaa
10705                bX|bbXb
10706                bX|bbX|b
10707                cccc"});
10708            assert_eq!(view.text(cx), expected_text);
10709            assert_eq!(view.selections.ranges(cx), expected_selections);
10710
10711            view.newline(&Newline, cx);
10712            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10713                aaaa
10714                bX
10715                |bbX
10716                b
10717                bX
10718                |bbX
10719                |b
10720                cccc"});
10721            assert_eq!(view.text(cx), expected_text);
10722            assert_eq!(view.selections.ranges(cx), expected_selections);
10723        });
10724    }
10725
10726    #[gpui::test]
10727    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
10728        cx.set_global(Settings::test(cx));
10729        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10730        let mut excerpt1_id = None;
10731        let multibuffer = cx.add_model(|cx| {
10732            let mut multibuffer = MultiBuffer::new(0);
10733            excerpt1_id = multibuffer
10734                .push_excerpts(
10735                    buffer.clone(),
10736                    [
10737                        ExcerptRange {
10738                            context: Point::new(0, 0)..Point::new(1, 4),
10739                            primary: None,
10740                        },
10741                        ExcerptRange {
10742                            context: Point::new(1, 0)..Point::new(2, 4),
10743                            primary: None,
10744                        },
10745                    ],
10746                    cx,
10747                )
10748                .into_iter()
10749                .next();
10750            multibuffer
10751        });
10752        assert_eq!(
10753            multibuffer.read(cx).read(cx).text(),
10754            "aaaa\nbbbb\nbbbb\ncccc"
10755        );
10756        let (_, editor) = cx.add_window(Default::default(), |cx| {
10757            let mut editor = build_editor(multibuffer.clone(), cx);
10758            let snapshot = editor.snapshot(cx);
10759            editor.change_selections(None, cx, |s| {
10760                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
10761            });
10762            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
10763            assert_eq!(
10764                editor.selections.ranges(cx),
10765                [
10766                    Point::new(1, 3)..Point::new(1, 3),
10767                    Point::new(2, 1)..Point::new(2, 1),
10768                ]
10769            );
10770            editor
10771        });
10772
10773        // Refreshing selections is a no-op when excerpts haven't changed.
10774        editor.update(cx, |editor, cx| {
10775            editor.change_selections(None, cx, |s| {
10776                s.refresh();
10777            });
10778            assert_eq!(
10779                editor.selections.ranges(cx),
10780                [
10781                    Point::new(1, 3)..Point::new(1, 3),
10782                    Point::new(2, 1)..Point::new(2, 1),
10783                ]
10784            );
10785        });
10786
10787        multibuffer.update(cx, |multibuffer, cx| {
10788            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10789        });
10790        editor.update(cx, |editor, cx| {
10791            // Removing an excerpt causes the first selection to become degenerate.
10792            assert_eq!(
10793                editor.selections.ranges(cx),
10794                [
10795                    Point::new(0, 0)..Point::new(0, 0),
10796                    Point::new(0, 1)..Point::new(0, 1)
10797                ]
10798            );
10799
10800            // Refreshing selections will relocate the first selection to the original buffer
10801            // location.
10802            editor.change_selections(None, cx, |s| {
10803                s.refresh();
10804            });
10805            assert_eq!(
10806                editor.selections.ranges(cx),
10807                [
10808                    Point::new(0, 1)..Point::new(0, 1),
10809                    Point::new(0, 3)..Point::new(0, 3)
10810                ]
10811            );
10812            assert!(editor.selections.pending_anchor().is_some());
10813        });
10814    }
10815
10816    #[gpui::test]
10817    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10818        cx.set_global(Settings::test(cx));
10819        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10820        let mut excerpt1_id = None;
10821        let multibuffer = cx.add_model(|cx| {
10822            let mut multibuffer = MultiBuffer::new(0);
10823            excerpt1_id = multibuffer
10824                .push_excerpts(
10825                    buffer.clone(),
10826                    [
10827                        ExcerptRange {
10828                            context: Point::new(0, 0)..Point::new(1, 4),
10829                            primary: None,
10830                        },
10831                        ExcerptRange {
10832                            context: Point::new(1, 0)..Point::new(2, 4),
10833                            primary: None,
10834                        },
10835                    ],
10836                    cx,
10837                )
10838                .into_iter()
10839                .next();
10840            multibuffer
10841        });
10842        assert_eq!(
10843            multibuffer.read(cx).read(cx).text(),
10844            "aaaa\nbbbb\nbbbb\ncccc"
10845        );
10846        let (_, editor) = cx.add_window(Default::default(), |cx| {
10847            let mut editor = build_editor(multibuffer.clone(), cx);
10848            let snapshot = editor.snapshot(cx);
10849            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10850            assert_eq!(
10851                editor.selections.ranges(cx),
10852                [Point::new(1, 3)..Point::new(1, 3)]
10853            );
10854            editor
10855        });
10856
10857        multibuffer.update(cx, |multibuffer, cx| {
10858            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10859        });
10860        editor.update(cx, |editor, cx| {
10861            assert_eq!(
10862                editor.selections.ranges(cx),
10863                [Point::new(0, 0)..Point::new(0, 0)]
10864            );
10865
10866            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10867            editor.change_selections(None, cx, |s| {
10868                s.refresh();
10869            });
10870            assert_eq!(
10871                editor.selections.ranges(cx),
10872                [Point::new(0, 3)..Point::new(0, 3)]
10873            );
10874            assert!(editor.selections.pending_anchor().is_some());
10875        });
10876    }
10877
10878    #[gpui::test]
10879    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10880        cx.update(|cx| cx.set_global(Settings::test(cx)));
10881        let language = Arc::new(
10882            Language::new(
10883                LanguageConfig {
10884                    brackets: vec![
10885                        BracketPair {
10886                            start: "{".to_string(),
10887                            end: "}".to_string(),
10888                            close: true,
10889                            newline: true,
10890                        },
10891                        BracketPair {
10892                            start: "/* ".to_string(),
10893                            end: " */".to_string(),
10894                            close: true,
10895                            newline: true,
10896                        },
10897                    ],
10898                    ..Default::default()
10899                },
10900                Some(tree_sitter_rust::language()),
10901            )
10902            .with_indents_query("")
10903            .unwrap(),
10904        );
10905
10906        let text = concat!(
10907            "{   }\n",     // Suppress rustfmt
10908            "  x\n",       //
10909            "  /*   */\n", //
10910            "x\n",         //
10911            "{{} }\n",     //
10912        );
10913
10914        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10915        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10916        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10917        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10918            .await;
10919
10920        view.update(cx, |view, cx| {
10921            view.change_selections(None, cx, |s| {
10922                s.select_display_ranges([
10923                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10924                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10925                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10926                ])
10927            });
10928            view.newline(&Newline, cx);
10929
10930            assert_eq!(
10931                view.buffer().read(cx).read(cx).text(),
10932                concat!(
10933                    "{ \n",    // Suppress rustfmt
10934                    "\n",      //
10935                    "}\n",     //
10936                    "  x\n",   //
10937                    "  /* \n", //
10938                    "  \n",    //
10939                    "  */\n",  //
10940                    "x\n",     //
10941                    "{{} \n",  //
10942                    "}\n",     //
10943                )
10944            );
10945        });
10946    }
10947
10948    #[gpui::test]
10949    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10950        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10951
10952        cx.set_global(Settings::test(cx));
10953        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10954
10955        editor.update(cx, |editor, cx| {
10956            struct Type1;
10957            struct Type2;
10958
10959            let buffer = buffer.read(cx).snapshot(cx);
10960
10961            let anchor_range = |range: Range<Point>| {
10962                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10963            };
10964
10965            editor.highlight_background::<Type1>(
10966                vec![
10967                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10968                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10969                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10970                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10971                ],
10972                |_| Color::red(),
10973                cx,
10974            );
10975            editor.highlight_background::<Type2>(
10976                vec![
10977                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10978                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10979                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10980                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10981                ],
10982                |_| Color::green(),
10983                cx,
10984            );
10985
10986            let snapshot = editor.snapshot(cx);
10987            let mut highlighted_ranges = editor.background_highlights_in_range(
10988                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10989                &snapshot,
10990                cx.global::<Settings>().theme.as_ref(),
10991            );
10992            // Enforce a consistent ordering based on color without relying on the ordering of the
10993            // highlight's `TypeId` which is non-deterministic.
10994            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10995            assert_eq!(
10996                highlighted_ranges,
10997                &[
10998                    (
10999                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
11000                        Color::green(),
11001                    ),
11002                    (
11003                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
11004                        Color::green(),
11005                    ),
11006                    (
11007                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
11008                        Color::red(),
11009                    ),
11010                    (
11011                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
11012                        Color::red(),
11013                    ),
11014                ]
11015            );
11016            assert_eq!(
11017                editor.background_highlights_in_range(
11018                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
11019                    &snapshot,
11020                    cx.global::<Settings>().theme.as_ref(),
11021                ),
11022                &[(
11023                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
11024                    Color::red(),
11025                )]
11026            );
11027        });
11028    }
11029
11030    #[gpui::test]
11031    fn test_following(cx: &mut gpui::MutableAppContext) {
11032        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
11033
11034        cx.set_global(Settings::test(cx));
11035
11036        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
11037        let (_, follower) = cx.add_window(
11038            WindowOptions {
11039                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
11040                ..Default::default()
11041            },
11042            |cx| build_editor(buffer.clone(), cx),
11043        );
11044
11045        let pending_update = Rc::new(RefCell::new(None));
11046        follower.update(cx, {
11047            let update = pending_update.clone();
11048            |_, cx| {
11049                cx.subscribe(&leader, move |_, leader, event, cx| {
11050                    leader
11051                        .read(cx)
11052                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
11053                })
11054                .detach();
11055            }
11056        });
11057
11058        // Update the selections only
11059        leader.update(cx, |leader, cx| {
11060            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
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![1..1]);
11068
11069        // Update the scroll position only
11070        leader.update(cx, |leader, cx| {
11071            leader.set_scroll_position(vec2f(1.5, 3.5), 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!(
11079            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
11080            vec2f(1.5, 3.5)
11081        );
11082
11083        // Update the selections and scroll position
11084        leader.update(cx, |leader, cx| {
11085            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
11086            leader.request_autoscroll(Autoscroll::Newest, cx);
11087            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
11088        });
11089        follower.update(cx, |follower, cx| {
11090            let initial_scroll_position = follower.scroll_position(cx);
11091            follower
11092                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11093                .unwrap();
11094            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
11095            assert!(follower.autoscroll_request.is_some());
11096        });
11097        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
11098
11099        // Creating a pending selection that precedes another selection
11100        leader.update(cx, |leader, cx| {
11101            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
11102            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
11103        });
11104        follower.update(cx, |follower, cx| {
11105            follower
11106                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11107                .unwrap();
11108        });
11109        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
11110
11111        // Extend the pending selection so that it surrounds another selection
11112        leader.update(cx, |leader, cx| {
11113            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
11114        });
11115        follower.update(cx, |follower, cx| {
11116            follower
11117                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11118                .unwrap();
11119        });
11120        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
11121    }
11122
11123    #[test]
11124    fn test_combine_syntax_and_fuzzy_match_highlights() {
11125        let string = "abcdefghijklmnop";
11126        let syntax_ranges = [
11127            (
11128                0..3,
11129                HighlightStyle {
11130                    color: Some(Color::red()),
11131                    ..Default::default()
11132                },
11133            ),
11134            (
11135                4..8,
11136                HighlightStyle {
11137                    color: Some(Color::green()),
11138                    ..Default::default()
11139                },
11140            ),
11141        ];
11142        let match_indices = [4, 6, 7, 8];
11143        assert_eq!(
11144            combine_syntax_and_fuzzy_match_highlights(
11145                &string,
11146                Default::default(),
11147                syntax_ranges.into_iter(),
11148                &match_indices,
11149            ),
11150            &[
11151                (
11152                    0..3,
11153                    HighlightStyle {
11154                        color: Some(Color::red()),
11155                        ..Default::default()
11156                    },
11157                ),
11158                (
11159                    4..5,
11160                    HighlightStyle {
11161                        color: Some(Color::green()),
11162                        weight: Some(fonts::Weight::BOLD),
11163                        ..Default::default()
11164                    },
11165                ),
11166                (
11167                    5..6,
11168                    HighlightStyle {
11169                        color: Some(Color::green()),
11170                        ..Default::default()
11171                    },
11172                ),
11173                (
11174                    6..8,
11175                    HighlightStyle {
11176                        color: Some(Color::green()),
11177                        weight: Some(fonts::Weight::BOLD),
11178                        ..Default::default()
11179                    },
11180                ),
11181                (
11182                    8..9,
11183                    HighlightStyle {
11184                        weight: Some(fonts::Weight::BOLD),
11185                        ..Default::default()
11186                    },
11187                ),
11188            ]
11189        );
11190    }
11191
11192    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
11193        let point = DisplayPoint::new(row as u32, column as u32);
11194        point..point
11195    }
11196
11197    fn assert_selection_ranges(
11198        marked_text: &str,
11199        selection_marker_pairs: Vec<(char, char)>,
11200        view: &mut Editor,
11201        cx: &mut ViewContext<Editor>,
11202    ) {
11203        let snapshot = view.snapshot(cx).display_snapshot;
11204        let mut marker_chars = Vec::new();
11205        for (start, end) in selection_marker_pairs.iter() {
11206            marker_chars.push(*start);
11207            marker_chars.push(*end);
11208        }
11209        let (_, markers) = marked_text_by(marked_text, marker_chars);
11210        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
11211            .iter()
11212            .map(|(start, end)| {
11213                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
11214                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
11215                start..end
11216            })
11217            .collect();
11218        assert_eq!(
11219            view.selections.display_ranges(cx),
11220            &asserted_ranges[..],
11221            "Assert selections are {}",
11222            marked_text
11223        );
11224    }
11225}
11226
11227trait RangeExt<T> {
11228    fn sorted(&self) -> Range<T>;
11229    fn to_inclusive(&self) -> RangeInclusive<T>;
11230}
11231
11232impl<T: Ord + Clone> RangeExt<T> for Range<T> {
11233    fn sorted(&self) -> Self {
11234        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
11235    }
11236
11237    fn to_inclusive(&self) -> RangeInclusive<T> {
11238        self.start.clone()..=self.end.clone()
11239    }
11240}
11241
11242trait RangeToAnchorExt {
11243    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
11244}
11245
11246impl<T: ToOffset> RangeToAnchorExt for Range<T> {
11247    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
11248        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
11249    }
11250}