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