editor.rs

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