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                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                return;
 4671            }
 4672        }
 4673
 4674        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 4675            active_diagnostics
 4676                .primary_range
 4677                .to_offset(&buffer)
 4678                .to_inclusive()
 4679        });
 4680        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 4681            if active_primary_range.contains(&selection.head()) {
 4682                *active_primary_range.end()
 4683            } else {
 4684                selection.head()
 4685            }
 4686        } else {
 4687            selection.head()
 4688        };
 4689
 4690        loop {
 4691            let mut diagnostics = if direction == Direction::Prev {
 4692                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 4693            } else {
 4694                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 4695            };
 4696            let group = diagnostics.find_map(|entry| {
 4697                if entry.diagnostic.is_primary
 4698                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 4699                    && !entry.range.is_empty()
 4700                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 4701                {
 4702                    Some((entry.range, entry.diagnostic.group_id))
 4703                } else {
 4704                    None
 4705                }
 4706            });
 4707
 4708            if let Some((primary_range, group_id)) = group {
 4709                self.activate_diagnostics(group_id, cx);
 4710                self.change_selections(Some(Autoscroll::Center), cx, |s| {
 4711                    s.select(vec![Selection {
 4712                        id: selection.id,
 4713                        start: primary_range.start,
 4714                        end: primary_range.start,
 4715                        reversed: false,
 4716                        goal: SelectionGoal::None,
 4717                    }]);
 4718                });
 4719                break;
 4720            } else {
 4721                // Cycle around to the start of the buffer, potentially moving back to the start of
 4722                // the currently active diagnostic.
 4723                active_primary_range.take();
 4724                if direction == Direction::Prev {
 4725                    if search_start == buffer.len() {
 4726                        break;
 4727                    } else {
 4728                        search_start = buffer.len();
 4729                    }
 4730                } else {
 4731                    if search_start == 0 {
 4732                        break;
 4733                    } else {
 4734                        search_start = 0;
 4735                    }
 4736                }
 4737            }
 4738        }
 4739    }
 4740
 4741    pub fn go_to_definition(
 4742        workspace: &mut Workspace,
 4743        _: &GoToDefinition,
 4744        cx: &mut ViewContext<Workspace>,
 4745    ) {
 4746        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
 4747    }
 4748
 4749    pub fn go_to_type_definition(
 4750        workspace: &mut Workspace,
 4751        _: &GoToTypeDefinition,
 4752        cx: &mut ViewContext<Workspace>,
 4753    ) {
 4754        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
 4755    }
 4756
 4757    fn go_to_definition_of_kind(
 4758        kind: GotoDefinitionKind,
 4759        workspace: &mut Workspace,
 4760        cx: &mut ViewContext<Workspace>,
 4761    ) {
 4762        let active_item = workspace.active_item(cx);
 4763        let editor_handle = if let Some(editor) = active_item
 4764            .as_ref()
 4765            .and_then(|item| item.act_as::<Self>(cx))
 4766        {
 4767            editor
 4768        } else {
 4769            return;
 4770        };
 4771
 4772        let editor = editor_handle.read(cx);
 4773        let buffer = editor.buffer.read(cx);
 4774        let head = editor.selections.newest::<usize>(cx).head();
 4775        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 4776            text_anchor
 4777        } else {
 4778            return;
 4779        };
 4780
 4781        let project = workspace.project().clone();
 4782        let definitions = project.update(cx, |project, cx| match kind {
 4783            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 4784            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 4785        });
 4786
 4787        cx.spawn(|workspace, mut cx| async move {
 4788            let definitions = definitions.await?;
 4789            workspace.update(&mut cx, |workspace, cx| {
 4790                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
 4791            });
 4792
 4793            Ok::<(), anyhow::Error>(())
 4794        })
 4795        .detach_and_log_err(cx);
 4796    }
 4797
 4798    pub fn navigate_to_definitions(
 4799        workspace: &mut Workspace,
 4800        editor_handle: ViewHandle<Editor>,
 4801        definitions: Vec<LocationLink>,
 4802        cx: &mut ViewContext<Workspace>,
 4803    ) {
 4804        let pane = workspace.active_pane().clone();
 4805        for definition in definitions {
 4806            let range = definition
 4807                .target
 4808                .range
 4809                .to_offset(definition.target.buffer.read(cx));
 4810
 4811            let target_editor_handle = workspace.open_project_item(definition.target.buffer, cx);
 4812            target_editor_handle.update(cx, |target_editor, cx| {
 4813                // When selecting a definition in a different buffer, disable the nav history
 4814                // to avoid creating a history entry at the previous cursor location.
 4815                if editor_handle != target_editor_handle {
 4816                    pane.update(cx, |pane, _| pane.disable_history());
 4817                }
 4818                target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
 4819                    s.select_ranges([range]);
 4820                });
 4821
 4822                pane.update(cx, |pane, _| pane.enable_history());
 4823            });
 4824        }
 4825    }
 4826
 4827    pub fn find_all_references(
 4828        workspace: &mut Workspace,
 4829        _: &FindAllReferences,
 4830        cx: &mut ViewContext<Workspace>,
 4831    ) -> Option<Task<Result<()>>> {
 4832        let active_item = workspace.active_item(cx)?;
 4833        let editor_handle = active_item.act_as::<Self>(cx)?;
 4834
 4835        let editor = editor_handle.read(cx);
 4836        let buffer = editor.buffer.read(cx);
 4837        let head = editor.selections.newest::<usize>(cx).head();
 4838        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 4839        let replica_id = editor.replica_id(cx);
 4840
 4841        let project = workspace.project().clone();
 4842        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 4843        Some(cx.spawn(|workspace, mut cx| async move {
 4844            let mut locations = references.await?;
 4845            if locations.is_empty() {
 4846                return Ok(());
 4847            }
 4848
 4849            locations.sort_by_key(|location| location.buffer.id());
 4850            let mut locations = locations.into_iter().peekable();
 4851            let mut ranges_to_highlight = Vec::new();
 4852
 4853            let excerpt_buffer = cx.add_model(|cx| {
 4854                let mut symbol_name = None;
 4855                let mut multibuffer = MultiBuffer::new(replica_id);
 4856                while let Some(location) = locations.next() {
 4857                    let buffer = location.buffer.read(cx);
 4858                    let mut ranges_for_buffer = Vec::new();
 4859                    let range = location.range.to_offset(buffer);
 4860                    ranges_for_buffer.push(range.clone());
 4861                    if symbol_name.is_none() {
 4862                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 4863                    }
 4864
 4865                    while let Some(next_location) = locations.peek() {
 4866                        if next_location.buffer == location.buffer {
 4867                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 4868                            locations.next();
 4869                        } else {
 4870                            break;
 4871                        }
 4872                    }
 4873
 4874                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 4875                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 4876                        location.buffer.clone(),
 4877                        ranges_for_buffer,
 4878                        1,
 4879                        cx,
 4880                    ));
 4881                }
 4882                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 4883            });
 4884
 4885            workspace.update(&mut cx, |workspace, cx| {
 4886                let editor =
 4887                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 4888                editor.update(cx, |editor, cx| {
 4889                    editor.highlight_background::<Self>(
 4890                        ranges_to_highlight,
 4891                        |theme| theme.editor.highlighted_line_background,
 4892                        cx,
 4893                    );
 4894                });
 4895                workspace.add_item(Box::new(editor), cx);
 4896            });
 4897
 4898            Ok(())
 4899        }))
 4900    }
 4901
 4902    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4903        use language::ToOffset as _;
 4904
 4905        let project = self.project.clone()?;
 4906        let selection = self.selections.newest_anchor().clone();
 4907        let (cursor_buffer, cursor_buffer_position) = self
 4908            .buffer
 4909            .read(cx)
 4910            .text_anchor_for_position(selection.head(), cx)?;
 4911        let (tail_buffer, _) = self
 4912            .buffer
 4913            .read(cx)
 4914            .text_anchor_for_position(selection.tail(), cx)?;
 4915        if tail_buffer != cursor_buffer {
 4916            return None;
 4917        }
 4918
 4919        let snapshot = cursor_buffer.read(cx).snapshot();
 4920        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4921        let prepare_rename = project.update(cx, |project, cx| {
 4922            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4923        });
 4924
 4925        Some(cx.spawn(|this, mut cx| async move {
 4926            let rename_range = if let Some(range) = prepare_rename.await? {
 4927                Some(range)
 4928            } else {
 4929                this.read_with(&cx, |this, cx| {
 4930                    let buffer = this.buffer.read(cx).snapshot(cx);
 4931                    let mut buffer_highlights = this
 4932                        .document_highlights_for_position(selection.head(), &buffer)
 4933                        .filter(|highlight| {
 4934                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 4935                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 4936                        });
 4937                    buffer_highlights
 4938                        .next()
 4939                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 4940                })
 4941            };
 4942            if let Some(rename_range) = rename_range {
 4943                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4944                let cursor_offset_in_rename_range =
 4945                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4946
 4947                this.update(&mut cx, |this, cx| {
 4948                    this.take_rename(false, cx);
 4949                    let style = this.style(cx);
 4950                    let buffer = this.buffer.read(cx).read(cx);
 4951                    let cursor_offset = selection.head().to_offset(&buffer);
 4952                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4953                    let rename_end = rename_start + rename_buffer_range.len();
 4954                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 4955                    let mut old_highlight_id = None;
 4956                    let old_name: Arc<str> = buffer
 4957                        .chunks(rename_start..rename_end, true)
 4958                        .map(|chunk| {
 4959                            if old_highlight_id.is_none() {
 4960                                old_highlight_id = chunk.syntax_highlight_id;
 4961                            }
 4962                            chunk.text
 4963                        })
 4964                        .collect::<String>()
 4965                        .into();
 4966
 4967                    drop(buffer);
 4968
 4969                    // Position the selection in the rename editor so that it matches the current selection.
 4970                    this.show_local_selections = false;
 4971                    let rename_editor = cx.add_view(|cx| {
 4972                        let mut editor = Editor::single_line(None, cx);
 4973                        if let Some(old_highlight_id) = old_highlight_id {
 4974                            editor.override_text_style =
 4975                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 4976                        }
 4977                        editor.buffer.update(cx, |buffer, cx| {
 4978                            buffer.edit([(0..0, old_name.clone())], None, cx)
 4979                        });
 4980                        editor.select_all(&SelectAll, cx);
 4981                        editor
 4982                    });
 4983
 4984                    let ranges = this
 4985                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 4986                        .into_iter()
 4987                        .flat_map(|(_, ranges)| ranges)
 4988                        .chain(
 4989                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 4990                                .into_iter()
 4991                                .flat_map(|(_, ranges)| ranges),
 4992                        )
 4993                        .collect();
 4994
 4995                    this.highlight_text::<Rename>(
 4996                        ranges,
 4997                        HighlightStyle {
 4998                            fade_out: Some(style.rename_fade),
 4999                            ..Default::default()
 5000                        },
 5001                        cx,
 5002                    );
 5003                    cx.focus(&rename_editor);
 5004                    let block_id = this.insert_blocks(
 5005                        [BlockProperties {
 5006                            style: BlockStyle::Flex,
 5007                            position: range.start.clone(),
 5008                            height: 1,
 5009                            render: Arc::new({
 5010                                let editor = rename_editor.clone();
 5011                                move |cx: &mut BlockContext| {
 5012                                    ChildView::new(editor.clone())
 5013                                        .contained()
 5014                                        .with_padding_left(cx.anchor_x)
 5015                                        .boxed()
 5016                                }
 5017                            }),
 5018                            disposition: BlockDisposition::Below,
 5019                        }],
 5020                        cx,
 5021                    )[0];
 5022                    this.pending_rename = Some(RenameState {
 5023                        range,
 5024                        old_name,
 5025                        editor: rename_editor,
 5026                        block_id,
 5027                    });
 5028                });
 5029            }
 5030
 5031            Ok(())
 5032        }))
 5033    }
 5034
 5035    pub fn confirm_rename(
 5036        workspace: &mut Workspace,
 5037        _: &ConfirmRename,
 5038        cx: &mut ViewContext<Workspace>,
 5039    ) -> Option<Task<Result<()>>> {
 5040        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 5041
 5042        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 5043            let rename = editor.take_rename(false, cx)?;
 5044            let buffer = editor.buffer.read(cx);
 5045            let (start_buffer, start) =
 5046                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 5047            let (end_buffer, end) =
 5048                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 5049            if start_buffer == end_buffer {
 5050                let new_name = rename.editor.read(cx).text(cx);
 5051                Some((start_buffer, start..end, rename.old_name, new_name))
 5052            } else {
 5053                None
 5054            }
 5055        })?;
 5056
 5057        let rename = workspace.project().clone().update(cx, |project, cx| {
 5058            project.perform_rename(
 5059                buffer.clone(),
 5060                range.start.clone(),
 5061                new_name.clone(),
 5062                true,
 5063                cx,
 5064            )
 5065        });
 5066
 5067        Some(cx.spawn(|workspace, mut cx| async move {
 5068            let project_transaction = rename.await?;
 5069            Self::open_project_transaction(
 5070                editor.clone(),
 5071                workspace,
 5072                project_transaction,
 5073                format!("Rename: {}{}", old_name, new_name),
 5074                cx.clone(),
 5075            )
 5076            .await?;
 5077
 5078            editor.update(&mut cx, |editor, cx| {
 5079                editor.refresh_document_highlights(cx);
 5080            });
 5081            Ok(())
 5082        }))
 5083    }
 5084
 5085    fn take_rename(
 5086        &mut self,
 5087        moving_cursor: bool,
 5088        cx: &mut ViewContext<Self>,
 5089    ) -> Option<RenameState> {
 5090        let rename = self.pending_rename.take()?;
 5091        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 5092        self.clear_text_highlights::<Rename>(cx);
 5093        self.show_local_selections = true;
 5094
 5095        if moving_cursor {
 5096            let rename_editor = rename.editor.read(cx);
 5097            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 5098
 5099            // Update the selection to match the position of the selection inside
 5100            // the rename editor.
 5101            let snapshot = self.buffer.read(cx).read(cx);
 5102            let rename_range = rename.range.to_offset(&snapshot);
 5103            let cursor_in_editor = snapshot
 5104                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 5105                .min(rename_range.end);
 5106            drop(snapshot);
 5107
 5108            self.change_selections(None, cx, |s| {
 5109                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 5110            });
 5111        } else {
 5112            self.refresh_document_highlights(cx);
 5113        }
 5114
 5115        Some(rename)
 5116    }
 5117
 5118    #[cfg(any(test, feature = "test-support"))]
 5119    pub fn pending_rename(&self) -> Option<&RenameState> {
 5120        self.pending_rename.as_ref()
 5121    }
 5122
 5123    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 5124        if let Some(project) = self.project.clone() {
 5125            self.buffer.update(cx, |multi_buffer, cx| {
 5126                project.update(cx, |project, cx| {
 5127                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 5128                });
 5129            })
 5130        }
 5131    }
 5132
 5133    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 5134        cx.show_character_palette();
 5135    }
 5136
 5137    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 5138        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 5139            let buffer = self.buffer.read(cx).snapshot(cx);
 5140            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 5141            let is_valid = buffer
 5142                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 5143                .any(|entry| {
 5144                    entry.diagnostic.is_primary
 5145                        && !entry.range.is_empty()
 5146                        && entry.range.start == primary_range_start
 5147                        && entry.diagnostic.message == active_diagnostics.primary_message
 5148                });
 5149
 5150            if is_valid != active_diagnostics.is_valid {
 5151                active_diagnostics.is_valid = is_valid;
 5152                let mut new_styles = HashMap::default();
 5153                for (block_id, diagnostic) in &active_diagnostics.blocks {
 5154                    new_styles.insert(
 5155                        *block_id,
 5156                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 5157                    );
 5158                }
 5159                self.display_map
 5160                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 5161            }
 5162        }
 5163    }
 5164
 5165    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 5166        self.dismiss_diagnostics(cx);
 5167        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 5168            let buffer = self.buffer.read(cx).snapshot(cx);
 5169
 5170            let mut primary_range = None;
 5171            let mut primary_message = None;
 5172            let mut group_end = Point::zero();
 5173            let diagnostic_group = buffer
 5174                .diagnostic_group::<Point>(group_id)
 5175                .map(|entry| {
 5176                    if entry.range.end > group_end {
 5177                        group_end = entry.range.end;
 5178                    }
 5179                    if entry.diagnostic.is_primary {
 5180                        primary_range = Some(entry.range.clone());
 5181                        primary_message = Some(entry.diagnostic.message.clone());
 5182                    }
 5183                    entry
 5184                })
 5185                .collect::<Vec<_>>();
 5186            let primary_range = primary_range.unwrap();
 5187            let primary_message = primary_message.unwrap();
 5188            let primary_range =
 5189                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 5190
 5191            let blocks = display_map
 5192                .insert_blocks(
 5193                    diagnostic_group.iter().map(|entry| {
 5194                        let diagnostic = entry.diagnostic.clone();
 5195                        let message_height = diagnostic.message.lines().count() as u8;
 5196                        BlockProperties {
 5197                            style: BlockStyle::Fixed,
 5198                            position: buffer.anchor_after(entry.range.start),
 5199                            height: message_height,
 5200                            render: diagnostic_block_renderer(diagnostic, true),
 5201                            disposition: BlockDisposition::Below,
 5202                        }
 5203                    }),
 5204                    cx,
 5205                )
 5206                .into_iter()
 5207                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 5208                .collect();
 5209
 5210            Some(ActiveDiagnosticGroup {
 5211                primary_range,
 5212                primary_message,
 5213                blocks,
 5214                is_valid: true,
 5215            })
 5216        });
 5217    }
 5218
 5219    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 5220        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 5221            self.display_map.update(cx, |display_map, cx| {
 5222                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 5223            });
 5224            cx.notify();
 5225        }
 5226    }
 5227
 5228    pub fn set_selections_from_remote(
 5229        &mut self,
 5230        selections: Vec<Selection<Anchor>>,
 5231        cx: &mut ViewContext<Self>,
 5232    ) {
 5233        let old_cursor_position = self.selections.newest_anchor().head();
 5234        self.selections.change_with(cx, |s| {
 5235            s.select_anchors(selections);
 5236        });
 5237        self.selections_did_change(false, &old_cursor_position, cx);
 5238    }
 5239
 5240    fn push_to_selection_history(&mut self) {
 5241        self.selection_history.push(SelectionHistoryEntry {
 5242            selections: self.selections.disjoint_anchors().clone(),
 5243            select_next_state: self.select_next_state.clone(),
 5244            add_selections_state: self.add_selections_state.clone(),
 5245        });
 5246    }
 5247
 5248    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5249        self.autoscroll_request = Some((autoscroll, true));
 5250        cx.notify();
 5251    }
 5252
 5253    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5254        self.autoscroll_request = Some((autoscroll, false));
 5255        cx.notify();
 5256    }
 5257
 5258    pub fn transact(
 5259        &mut self,
 5260        cx: &mut ViewContext<Self>,
 5261        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5262    ) -> Option<TransactionId> {
 5263        self.start_transaction_at(Instant::now(), cx);
 5264        update(self, cx);
 5265        self.end_transaction_at(Instant::now(), cx)
 5266    }
 5267
 5268    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5269        self.end_selection(cx);
 5270        if let Some(tx_id) = self
 5271            .buffer
 5272            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5273        {
 5274            self.selection_history
 5275                .insert_transaction(tx_id, self.selections.disjoint_anchors().clone());
 5276        }
 5277    }
 5278
 5279    fn end_transaction_at(
 5280        &mut self,
 5281        now: Instant,
 5282        cx: &mut ViewContext<Self>,
 5283    ) -> Option<TransactionId> {
 5284        if let Some(tx_id) = self
 5285            .buffer
 5286            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5287        {
 5288            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5289                *end_selections = Some(self.selections.disjoint_anchors().clone());
 5290            } else {
 5291                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5292            }
 5293
 5294            cx.emit(Event::Edited);
 5295            Some(tx_id)
 5296        } else {
 5297            None
 5298        }
 5299    }
 5300
 5301    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5302        log::info!("Editor::page_up");
 5303    }
 5304
 5305    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5306        log::info!("Editor::page_down");
 5307    }
 5308
 5309    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5310        let mut fold_ranges = Vec::new();
 5311
 5312        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5313        let selections = self.selections.all::<Point>(cx);
 5314        for selection in selections {
 5315            let range = selection.display_range(&display_map).sorted();
 5316            let buffer_start_row = range.start.to_point(&display_map).row;
 5317
 5318            for row in (0..=range.end.row()).rev() {
 5319                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5320                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5321                    if fold_range.end.row >= buffer_start_row {
 5322                        fold_ranges.push(fold_range);
 5323                        if row <= range.start.row() {
 5324                            break;
 5325                        }
 5326                    }
 5327                }
 5328            }
 5329        }
 5330
 5331        self.fold_ranges(fold_ranges, cx);
 5332    }
 5333
 5334    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5335        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5336        let buffer = &display_map.buffer_snapshot;
 5337        let selections = self.selections.all::<Point>(cx);
 5338        let ranges = selections
 5339            .iter()
 5340            .map(|s| {
 5341                let range = s.display_range(&display_map).sorted();
 5342                let mut start = range.start.to_point(&display_map);
 5343                let mut end = range.end.to_point(&display_map);
 5344                start.column = 0;
 5345                end.column = buffer.line_len(end.row);
 5346                start..end
 5347            })
 5348            .collect::<Vec<_>>();
 5349        self.unfold_ranges(ranges, true, cx);
 5350    }
 5351
 5352    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5353        let max_point = display_map.max_point();
 5354        if display_row >= max_point.row() {
 5355            false
 5356        } else {
 5357            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5358            if is_blank {
 5359                false
 5360            } else {
 5361                for display_row in display_row + 1..=max_point.row() {
 5362                    let (indent, is_blank) = display_map.line_indent(display_row);
 5363                    if !is_blank {
 5364                        return indent > start_indent;
 5365                    }
 5366                }
 5367                false
 5368            }
 5369        }
 5370    }
 5371
 5372    fn foldable_range_for_line(
 5373        &self,
 5374        display_map: &DisplaySnapshot,
 5375        start_row: u32,
 5376    ) -> Range<Point> {
 5377        let max_point = display_map.max_point();
 5378
 5379        let (start_indent, _) = display_map.line_indent(start_row);
 5380        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5381        let mut end = None;
 5382        for row in start_row + 1..=max_point.row() {
 5383            let (indent, is_blank) = display_map.line_indent(row);
 5384            if !is_blank && indent <= start_indent {
 5385                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5386                break;
 5387            }
 5388        }
 5389
 5390        let end = end.unwrap_or(max_point);
 5391        return start.to_point(display_map)..end.to_point(display_map);
 5392    }
 5393
 5394    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5395        let selections = self.selections.all::<Point>(cx);
 5396        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5397        self.fold_ranges(ranges, cx);
 5398    }
 5399
 5400    pub fn fold_ranges<T: ToOffset>(
 5401        &mut self,
 5402        ranges: impl IntoIterator<Item = Range<T>>,
 5403        cx: &mut ViewContext<Self>,
 5404    ) {
 5405        let mut ranges = ranges.into_iter().peekable();
 5406        if ranges.peek().is_some() {
 5407            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5408            self.request_autoscroll(Autoscroll::Fit, cx);
 5409            cx.notify();
 5410        }
 5411    }
 5412
 5413    pub fn unfold_ranges<T: ToOffset>(
 5414        &mut self,
 5415        ranges: impl IntoIterator<Item = Range<T>>,
 5416        inclusive: bool,
 5417        cx: &mut ViewContext<Self>,
 5418    ) {
 5419        let mut ranges = ranges.into_iter().peekable();
 5420        if ranges.peek().is_some() {
 5421            self.display_map
 5422                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5423            self.request_autoscroll(Autoscroll::Fit, cx);
 5424            cx.notify();
 5425        }
 5426    }
 5427
 5428    pub fn insert_blocks(
 5429        &mut self,
 5430        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5431        cx: &mut ViewContext<Self>,
 5432    ) -> Vec<BlockId> {
 5433        let blocks = self
 5434            .display_map
 5435            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5436        self.request_autoscroll(Autoscroll::Fit, cx);
 5437        blocks
 5438    }
 5439
 5440    pub fn replace_blocks(
 5441        &mut self,
 5442        blocks: HashMap<BlockId, RenderBlock>,
 5443        cx: &mut ViewContext<Self>,
 5444    ) {
 5445        self.display_map
 5446            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5447        self.request_autoscroll(Autoscroll::Fit, cx);
 5448    }
 5449
 5450    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5451        self.display_map.update(cx, |display_map, cx| {
 5452            display_map.remove_blocks(block_ids, cx)
 5453        });
 5454    }
 5455
 5456    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5457        self.display_map
 5458            .update(cx, |map, cx| map.snapshot(cx))
 5459            .longest_row()
 5460    }
 5461
 5462    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5463        self.display_map
 5464            .update(cx, |map, cx| map.snapshot(cx))
 5465            .max_point()
 5466    }
 5467
 5468    pub fn text(&self, cx: &AppContext) -> String {
 5469        self.buffer.read(cx).read(cx).text()
 5470    }
 5471
 5472    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 5473        self.transact(cx, |this, cx| {
 5474            this.buffer
 5475                .read(cx)
 5476                .as_singleton()
 5477                .expect("you can only call set_text on editors for singleton buffers")
 5478                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5479        });
 5480    }
 5481
 5482    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5483        self.display_map
 5484            .update(cx, |map, cx| map.snapshot(cx))
 5485            .text()
 5486    }
 5487
 5488    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5489        let language_name = self
 5490            .buffer
 5491            .read(cx)
 5492            .as_singleton()
 5493            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5494            .map(|l| l.name());
 5495
 5496        let settings = cx.global::<Settings>();
 5497        let mode = self
 5498            .soft_wrap_mode_override
 5499            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5500        match mode {
 5501            settings::SoftWrap::None => SoftWrap::None,
 5502            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5503            settings::SoftWrap::PreferredLineLength => {
 5504                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5505            }
 5506        }
 5507    }
 5508
 5509    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5510        self.soft_wrap_mode_override = Some(mode);
 5511        cx.notify();
 5512    }
 5513
 5514    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5515        self.display_map
 5516            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5517    }
 5518
 5519    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5520        self.highlighted_rows = rows;
 5521    }
 5522
 5523    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5524        self.highlighted_rows.clone()
 5525    }
 5526
 5527    pub fn highlight_background<T: 'static>(
 5528        &mut self,
 5529        ranges: Vec<Range<Anchor>>,
 5530        color_fetcher: fn(&Theme) -> Color,
 5531        cx: &mut ViewContext<Self>,
 5532    ) {
 5533        self.background_highlights
 5534            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5535        cx.notify();
 5536    }
 5537
 5538    pub fn clear_background_highlights<T: 'static>(
 5539        &mut self,
 5540        cx: &mut ViewContext<Self>,
 5541    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5542        cx.notify();
 5543        self.background_highlights.remove(&TypeId::of::<T>())
 5544    }
 5545
 5546    #[cfg(feature = "test-support")]
 5547    pub fn all_background_highlights(
 5548        &mut self,
 5549        cx: &mut ViewContext<Self>,
 5550    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5551        let snapshot = self.snapshot(cx);
 5552        let buffer = &snapshot.buffer_snapshot;
 5553        let start = buffer.anchor_before(0);
 5554        let end = buffer.anchor_after(buffer.len());
 5555        let theme = cx.global::<Settings>().theme.as_ref();
 5556        self.background_highlights_in_range(start..end, &snapshot, theme)
 5557    }
 5558
 5559    fn document_highlights_for_position<'a>(
 5560        &'a self,
 5561        position: Anchor,
 5562        buffer: &'a MultiBufferSnapshot,
 5563    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5564        let read_highlights = self
 5565            .background_highlights
 5566            .get(&TypeId::of::<DocumentHighlightRead>())
 5567            .map(|h| &h.1);
 5568        let write_highlights = self
 5569            .background_highlights
 5570            .get(&TypeId::of::<DocumentHighlightWrite>())
 5571            .map(|h| &h.1);
 5572        let left_position = position.bias_left(buffer);
 5573        let right_position = position.bias_right(buffer);
 5574        read_highlights
 5575            .into_iter()
 5576            .chain(write_highlights)
 5577            .flat_map(move |ranges| {
 5578                let start_ix = match ranges.binary_search_by(|probe| {
 5579                    let cmp = probe.end.cmp(&left_position, &buffer);
 5580                    if cmp.is_ge() {
 5581                        Ordering::Greater
 5582                    } else {
 5583                        Ordering::Less
 5584                    }
 5585                }) {
 5586                    Ok(i) | Err(i) => i,
 5587                };
 5588
 5589                let right_position = right_position.clone();
 5590                ranges[start_ix..]
 5591                    .iter()
 5592                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
 5593            })
 5594    }
 5595
 5596    pub fn background_highlights_in_range(
 5597        &self,
 5598        search_range: Range<Anchor>,
 5599        display_snapshot: &DisplaySnapshot,
 5600        theme: &Theme,
 5601    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5602        let mut results = Vec::new();
 5603        let buffer = &display_snapshot.buffer_snapshot;
 5604        for (color_fetcher, ranges) in self.background_highlights.values() {
 5605            let color = color_fetcher(theme);
 5606            let start_ix = match ranges.binary_search_by(|probe| {
 5607                let cmp = probe.end.cmp(&search_range.start, &buffer);
 5608                if cmp.is_gt() {
 5609                    Ordering::Greater
 5610                } else {
 5611                    Ordering::Less
 5612                }
 5613            }) {
 5614                Ok(i) | Err(i) => i,
 5615            };
 5616            for range in &ranges[start_ix..] {
 5617                if range.start.cmp(&search_range.end, &buffer).is_ge() {
 5618                    break;
 5619                }
 5620                let start = range
 5621                    .start
 5622                    .to_point(buffer)
 5623                    .to_display_point(display_snapshot);
 5624                let end = range
 5625                    .end
 5626                    .to_point(buffer)
 5627                    .to_display_point(display_snapshot);
 5628                results.push((start..end, color))
 5629            }
 5630        }
 5631        results
 5632    }
 5633
 5634    pub fn highlight_text<T: 'static>(
 5635        &mut self,
 5636        ranges: Vec<Range<Anchor>>,
 5637        style: HighlightStyle,
 5638        cx: &mut ViewContext<Self>,
 5639    ) {
 5640        self.display_map.update(cx, |map, _| {
 5641            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5642        });
 5643        cx.notify();
 5644    }
 5645
 5646    pub fn text_highlights<'a, T: 'static>(
 5647        &'a self,
 5648        cx: &'a AppContext,
 5649    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 5650        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 5651    }
 5652
 5653    pub fn clear_text_highlights<T: 'static>(
 5654        &mut self,
 5655        cx: &mut ViewContext<Self>,
 5656    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5657        cx.notify();
 5658        self.display_map
 5659            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5660    }
 5661
 5662    fn next_blink_epoch(&mut self) -> usize {
 5663        self.blink_epoch += 1;
 5664        self.blink_epoch
 5665    }
 5666
 5667    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5668        if !self.focused {
 5669            return;
 5670        }
 5671
 5672        self.show_local_cursors = true;
 5673        cx.notify();
 5674
 5675        let epoch = self.next_blink_epoch();
 5676        cx.spawn(|this, mut cx| {
 5677            let this = this.downgrade();
 5678            async move {
 5679                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5680                if let Some(this) = this.upgrade(&cx) {
 5681                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5682                }
 5683            }
 5684        })
 5685        .detach();
 5686    }
 5687
 5688    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5689        if epoch == self.blink_epoch {
 5690            self.blinking_paused = false;
 5691            self.blink_cursors(epoch, cx);
 5692        }
 5693    }
 5694
 5695    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5696        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5697            self.show_local_cursors = !self.show_local_cursors;
 5698            cx.notify();
 5699
 5700            let epoch = self.next_blink_epoch();
 5701            cx.spawn(|this, mut cx| {
 5702                let this = this.downgrade();
 5703                async move {
 5704                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5705                    if let Some(this) = this.upgrade(&cx) {
 5706                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5707                    }
 5708                }
 5709            })
 5710            .detach();
 5711        }
 5712    }
 5713
 5714    pub fn show_local_cursors(&self) -> bool {
 5715        self.show_local_cursors && self.focused
 5716    }
 5717
 5718    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5719        cx.notify();
 5720    }
 5721
 5722    fn on_buffer_event(
 5723        &mut self,
 5724        _: ModelHandle<MultiBuffer>,
 5725        event: &language::Event,
 5726        cx: &mut ViewContext<Self>,
 5727    ) {
 5728        match event {
 5729            language::Event::Edited => {
 5730                self.refresh_active_diagnostics(cx);
 5731                self.refresh_code_actions(cx);
 5732                cx.emit(Event::BufferEdited);
 5733            }
 5734            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5735            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
 5736            language::Event::Saved => cx.emit(Event::Saved),
 5737            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5738            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5739            language::Event::Closed => cx.emit(Event::Closed),
 5740            language::Event::DiagnosticsUpdated => {
 5741                self.refresh_active_diagnostics(cx);
 5742            }
 5743            _ => {}
 5744        }
 5745    }
 5746
 5747    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5748        cx.notify();
 5749    }
 5750
 5751    pub fn set_searchable(&mut self, searchable: bool) {
 5752        self.searchable = searchable;
 5753    }
 5754
 5755    pub fn searchable(&self) -> bool {
 5756        self.searchable
 5757    }
 5758
 5759    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5760        let active_item = workspace.active_item(cx);
 5761        let editor_handle = if let Some(editor) = active_item
 5762            .as_ref()
 5763            .and_then(|item| item.act_as::<Self>(cx))
 5764        {
 5765            editor
 5766        } else {
 5767            cx.propagate_action();
 5768            return;
 5769        };
 5770
 5771        let editor = editor_handle.read(cx);
 5772        let buffer = editor.buffer.read(cx);
 5773        if buffer.is_singleton() {
 5774            cx.propagate_action();
 5775            return;
 5776        }
 5777
 5778        let mut new_selections_by_buffer = HashMap::default();
 5779        for selection in editor.selections.all::<usize>(cx) {
 5780            for (buffer, mut range) in
 5781                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5782            {
 5783                if selection.reversed {
 5784                    mem::swap(&mut range.start, &mut range.end);
 5785                }
 5786                new_selections_by_buffer
 5787                    .entry(buffer)
 5788                    .or_insert(Vec::new())
 5789                    .push(range)
 5790            }
 5791        }
 5792
 5793        editor_handle.update(cx, |editor, cx| {
 5794            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 5795        });
 5796        let pane = workspace.active_pane().clone();
 5797        pane.update(cx, |pane, _| pane.disable_history());
 5798
 5799        // We defer the pane interaction because we ourselves are a workspace item
 5800        // and activating a new item causes the pane to call a method on us reentrantly,
 5801        // which panics if we're on the stack.
 5802        cx.defer(move |workspace, cx| {
 5803            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5804                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5805                editor.update(cx, |editor, cx| {
 5806                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5807                        s.select_ranges(ranges);
 5808                    });
 5809                });
 5810            }
 5811
 5812            pane.update(cx, |pane, _| pane.enable_history());
 5813        });
 5814    }
 5815
 5816    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
 5817        let editor = workspace.open_path(action.path.clone(), true, cx);
 5818        let position = action.position;
 5819        let anchor = action.anchor;
 5820        cx.spawn_weak(|_, mut cx| async move {
 5821            let editor = editor.await.log_err()?.downcast::<Editor>()?;
 5822            editor.update(&mut cx, |editor, cx| {
 5823                let buffer = editor.buffer().read(cx).as_singleton()?;
 5824                let buffer = buffer.read(cx);
 5825                let cursor = if buffer.can_resolve(&anchor) {
 5826                    language::ToPoint::to_point(&anchor, buffer)
 5827                } else {
 5828                    buffer.clip_point(position, Bias::Left)
 5829                };
 5830
 5831                let nav_history = editor.nav_history.take();
 5832                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5833                    s.select_ranges([cursor..cursor]);
 5834                });
 5835                editor.nav_history = nav_history;
 5836
 5837                Some(())
 5838            })?;
 5839            Some(())
 5840        })
 5841        .detach()
 5842    }
 5843
 5844    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 5845        let snapshot = self.buffer.read(cx).read(cx);
 5846        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 5847        Some(
 5848            ranges
 5849                .into_iter()
 5850                .map(move |range| {
 5851                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 5852                })
 5853                .collect(),
 5854        )
 5855    }
 5856
 5857    fn selection_replacement_ranges(
 5858        &self,
 5859        range: Range<OffsetUtf16>,
 5860        cx: &AppContext,
 5861    ) -> Vec<Range<OffsetUtf16>> {
 5862        let selections = self.selections.all::<OffsetUtf16>(cx);
 5863        let newest_selection = selections
 5864            .iter()
 5865            .max_by_key(|selection| selection.id)
 5866            .unwrap();
 5867        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 5868        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 5869        let snapshot = self.buffer.read(cx).read(cx);
 5870        selections
 5871            .into_iter()
 5872            .map(|mut selection| {
 5873                selection.start.0 =
 5874                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 5875                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 5876                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 5877                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 5878            })
 5879            .collect()
 5880    }
 5881}
 5882
 5883impl EditorSnapshot {
 5884    pub fn is_focused(&self) -> bool {
 5885        self.is_focused
 5886    }
 5887
 5888    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5889        self.placeholder_text.as_ref()
 5890    }
 5891
 5892    pub fn scroll_position(&self) -> Vector2F {
 5893        compute_scroll_position(
 5894            &self.display_snapshot,
 5895            self.scroll_position,
 5896            &self.scroll_top_anchor,
 5897        )
 5898    }
 5899}
 5900
 5901impl Deref for EditorSnapshot {
 5902    type Target = DisplaySnapshot;
 5903
 5904    fn deref(&self) -> &Self::Target {
 5905        &self.display_snapshot
 5906    }
 5907}
 5908
 5909fn compute_scroll_position(
 5910    snapshot: &DisplaySnapshot,
 5911    mut scroll_position: Vector2F,
 5912    scroll_top_anchor: &Anchor,
 5913) -> Vector2F {
 5914    if *scroll_top_anchor != Anchor::min() {
 5915        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5916        scroll_position.set_y(scroll_top + scroll_position.y());
 5917    } else {
 5918        scroll_position.set_y(0.);
 5919    }
 5920    scroll_position
 5921}
 5922
 5923#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5924pub enum Event {
 5925    Activate,
 5926    BufferEdited,
 5927    Edited,
 5928    Reparsed,
 5929    Blurred,
 5930    DirtyChanged,
 5931    Saved,
 5932    TitleChanged,
 5933    SelectionsChanged { local: bool },
 5934    ScrollPositionChanged { local: bool },
 5935    Closed,
 5936    IgnoredInput,
 5937}
 5938
 5939pub struct EditorFocused(pub ViewHandle<Editor>);
 5940pub struct EditorBlurred(pub ViewHandle<Editor>);
 5941pub struct EditorReleased(pub WeakViewHandle<Editor>);
 5942
 5943impl Entity for Editor {
 5944    type Event = Event;
 5945
 5946    fn release(&mut self, cx: &mut MutableAppContext) {
 5947        cx.emit_global(EditorReleased(self.handle.clone()));
 5948    }
 5949}
 5950
 5951impl View for Editor {
 5952    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 5953        let style = self.style(cx);
 5954        let font_changed = self.display_map.update(cx, |map, cx| {
 5955            map.set_font(style.text.font_id, style.text.font_size, cx)
 5956        });
 5957
 5958        if font_changed {
 5959            let handle = self.handle.clone();
 5960            cx.defer(move |cx| {
 5961                if let Some(editor) = handle.upgrade(cx) {
 5962                    editor.update(cx, |editor, cx| {
 5963                        hide_hover(editor, cx);
 5964                    })
 5965                }
 5966            });
 5967        }
 5968
 5969        Stack::new()
 5970            .with_child(
 5971                EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed(),
 5972            )
 5973            .with_child(ChildView::new(&self.mouse_context_menu).boxed())
 5974            .boxed()
 5975    }
 5976
 5977    fn ui_name() -> &'static str {
 5978        "Editor"
 5979    }
 5980
 5981    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 5982        let focused_event = EditorFocused(cx.handle());
 5983        cx.emit_global(focused_event);
 5984        if let Some(rename) = self.pending_rename.as_ref() {
 5985            cx.focus(&rename.editor);
 5986        } else {
 5987            self.focused = true;
 5988            self.blink_cursors(self.blink_epoch, cx);
 5989            self.buffer.update(cx, |buffer, cx| {
 5990                buffer.finalize_last_transaction(cx);
 5991                if self.leader_replica_id.is_none() {
 5992                    buffer.set_active_selections(
 5993                        &self.selections.disjoint_anchors(),
 5994                        self.selections.line_mode,
 5995                        cx,
 5996                    );
 5997                }
 5998            });
 5999        }
 6000    }
 6001
 6002    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 6003        let blurred_event = EditorBlurred(cx.handle());
 6004        cx.emit_global(blurred_event);
 6005        self.focused = false;
 6006        self.buffer
 6007            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6008        self.hide_context_menu(cx);
 6009        hide_hover(self, cx);
 6010        cx.emit(Event::Blurred);
 6011        cx.notify();
 6012    }
 6013
 6014    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6015        let mut context = Self::default_keymap_context();
 6016        let mode = match self.mode {
 6017            EditorMode::SingleLine => "single_line",
 6018            EditorMode::AutoHeight { .. } => "auto_height",
 6019            EditorMode::Full => "full",
 6020        };
 6021        context.map.insert("mode".into(), mode.into());
 6022        if self.pending_rename.is_some() {
 6023            context.set.insert("renaming".into());
 6024        }
 6025        match self.context_menu.as_ref() {
 6026            Some(ContextMenu::Completions(_)) => {
 6027                context.set.insert("showing_completions".into());
 6028            }
 6029            Some(ContextMenu::CodeActions(_)) => {
 6030                context.set.insert("showing_code_actions".into());
 6031            }
 6032            None => {}
 6033        }
 6034
 6035        for layer in self.keymap_context_layers.values() {
 6036            context.extend(layer);
 6037        }
 6038
 6039        context
 6040    }
 6041
 6042    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
 6043        Some(
 6044            self.buffer
 6045                .read(cx)
 6046                .read(cx)
 6047                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 6048                .collect(),
 6049        )
 6050    }
 6051
 6052    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6053        // Prevent the IME menu from appearing when holding down an alphabetic key
 6054        // while input is disabled.
 6055        if !self.input_enabled {
 6056            return None;
 6057        }
 6058
 6059        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 6060        Some(range.start.0..range.end.0)
 6061    }
 6062
 6063    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6064        let snapshot = self.buffer.read(cx).read(cx);
 6065        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 6066        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 6067    }
 6068
 6069    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 6070        self.clear_text_highlights::<InputComposition>(cx);
 6071        self.ime_transaction.take();
 6072    }
 6073
 6074    fn replace_text_in_range(
 6075        &mut self,
 6076        range_utf16: Option<Range<usize>>,
 6077        text: &str,
 6078        cx: &mut ViewContext<Self>,
 6079    ) {
 6080        if !self.input_enabled {
 6081            cx.emit(Event::IgnoredInput);
 6082            return;
 6083        }
 6084
 6085        self.transact(cx, |this, cx| {
 6086            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 6087                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6088                Some(this.selection_replacement_ranges(range_utf16, cx))
 6089            } else if let Some(marked_ranges) = this.marked_text_ranges(cx) {
 6090                Some(marked_ranges)
 6091            } else {
 6092                None
 6093            };
 6094
 6095            if let Some(new_selected_ranges) = new_selected_ranges {
 6096                this.change_selections(None, cx, |selections| {
 6097                    selections.select_ranges(new_selected_ranges)
 6098                });
 6099            }
 6100            this.handle_input(text, cx);
 6101        });
 6102
 6103        if let Some(transaction) = self.ime_transaction {
 6104            self.buffer.update(cx, |buffer, cx| {
 6105                buffer.group_until_transaction(transaction, cx);
 6106            });
 6107        }
 6108
 6109        self.unmark_text(cx);
 6110    }
 6111
 6112    fn replace_and_mark_text_in_range(
 6113        &mut self,
 6114        range_utf16: Option<Range<usize>>,
 6115        text: &str,
 6116        new_selected_range_utf16: Option<Range<usize>>,
 6117        cx: &mut ViewContext<Self>,
 6118    ) {
 6119        if !self.input_enabled {
 6120            cx.emit(Event::IgnoredInput);
 6121            return;
 6122        }
 6123
 6124        let transaction = self.transact(cx, |this, cx| {
 6125            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 6126                let snapshot = this.buffer.read(cx).read(cx);
 6127                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 6128                    for marked_range in &mut marked_ranges {
 6129                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 6130                        marked_range.start.0 += relative_range_utf16.start;
 6131                        marked_range.start =
 6132                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 6133                        marked_range.end =
 6134                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 6135                    }
 6136                }
 6137                Some(marked_ranges)
 6138            } else if let Some(range_utf16) = range_utf16 {
 6139                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6140                Some(this.selection_replacement_ranges(range_utf16, cx))
 6141            } else {
 6142                None
 6143            };
 6144
 6145            if let Some(ranges) = ranges_to_replace {
 6146                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 6147            }
 6148
 6149            let marked_ranges = {
 6150                let snapshot = this.buffer.read(cx).read(cx);
 6151                this.selections
 6152                    .disjoint_anchors()
 6153                    .into_iter()
 6154                    .map(|selection| {
 6155                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 6156                    })
 6157                    .collect::<Vec<_>>()
 6158            };
 6159
 6160            if text.is_empty() {
 6161                this.unmark_text(cx);
 6162            } else {
 6163                this.highlight_text::<InputComposition>(
 6164                    marked_ranges.clone(),
 6165                    this.style(cx).composition_mark,
 6166                    cx,
 6167                );
 6168            }
 6169
 6170            this.handle_input(text, cx);
 6171
 6172            if let Some(new_selected_range) = new_selected_range_utf16 {
 6173                let snapshot = this.buffer.read(cx).read(cx);
 6174                let new_selected_ranges = marked_ranges
 6175                    .into_iter()
 6176                    .map(|marked_range| {
 6177                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 6178                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 6179                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 6180                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 6181                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 6182                    })
 6183                    .collect::<Vec<_>>();
 6184
 6185                drop(snapshot);
 6186                this.change_selections(None, cx, |selections| {
 6187                    selections.select_ranges(new_selected_ranges)
 6188                });
 6189            }
 6190        });
 6191
 6192        self.ime_transaction = self.ime_transaction.or(transaction);
 6193        if let Some(transaction) = self.ime_transaction {
 6194            self.buffer.update(cx, |buffer, cx| {
 6195                buffer.group_until_transaction(transaction, cx);
 6196            });
 6197        }
 6198
 6199        if self.text_highlights::<InputComposition>(cx).is_none() {
 6200            self.ime_transaction.take();
 6201        }
 6202    }
 6203}
 6204
 6205fn build_style(
 6206    settings: &Settings,
 6207    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6208    override_text_style: Option<&OverrideTextStyle>,
 6209    cx: &AppContext,
 6210) -> EditorStyle {
 6211    let font_cache = cx.font_cache();
 6212
 6213    let mut theme = settings.theme.editor.clone();
 6214    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6215        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6216        theme.text_color = field_editor_theme.text.color;
 6217        theme.selection = field_editor_theme.selection;
 6218        theme.background = field_editor_theme
 6219            .container
 6220            .background_color
 6221            .unwrap_or_default();
 6222        EditorStyle {
 6223            text: field_editor_theme.text,
 6224            placeholder_text: field_editor_theme.placeholder_text,
 6225            theme,
 6226        }
 6227    } else {
 6228        let font_family_id = settings.buffer_font_family;
 6229        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6230        let font_properties = Default::default();
 6231        let font_id = font_cache
 6232            .select_font(font_family_id, &font_properties)
 6233            .unwrap();
 6234        let font_size = settings.buffer_font_size;
 6235        EditorStyle {
 6236            text: TextStyle {
 6237                color: settings.theme.editor.text_color,
 6238                font_family_name,
 6239                font_family_id,
 6240                font_id,
 6241                font_size,
 6242                font_properties,
 6243                underline: Default::default(),
 6244            },
 6245            placeholder_text: None,
 6246            theme,
 6247        }
 6248    };
 6249
 6250    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6251        if let Some(highlighted) = style
 6252            .text
 6253            .clone()
 6254            .highlight(highlight_style, font_cache)
 6255            .log_err()
 6256        {
 6257            style.text = highlighted;
 6258        }
 6259    }
 6260
 6261    style
 6262}
 6263
 6264trait SelectionExt {
 6265    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6266    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6267    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6268    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6269        -> Range<u32>;
 6270}
 6271
 6272impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6273    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6274        let start = self.start.to_point(buffer);
 6275        let end = self.end.to_point(buffer);
 6276        if self.reversed {
 6277            end..start
 6278        } else {
 6279            start..end
 6280        }
 6281    }
 6282
 6283    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6284        let start = self.start.to_offset(buffer);
 6285        let end = self.end.to_offset(buffer);
 6286        if self.reversed {
 6287            end..start
 6288        } else {
 6289            start..end
 6290        }
 6291    }
 6292
 6293    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6294        let start = self
 6295            .start
 6296            .to_point(&map.buffer_snapshot)
 6297            .to_display_point(map);
 6298        let end = self
 6299            .end
 6300            .to_point(&map.buffer_snapshot)
 6301            .to_display_point(map);
 6302        if self.reversed {
 6303            end..start
 6304        } else {
 6305            start..end
 6306        }
 6307    }
 6308
 6309    fn spanned_rows(
 6310        &self,
 6311        include_end_if_at_line_start: bool,
 6312        map: &DisplaySnapshot,
 6313    ) -> Range<u32> {
 6314        let start = self.start.to_point(&map.buffer_snapshot);
 6315        let mut end = self.end.to_point(&map.buffer_snapshot);
 6316        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6317            end.row -= 1;
 6318        }
 6319
 6320        let buffer_start = map.prev_line_boundary(start).0;
 6321        let buffer_end = map.next_line_boundary(end).0;
 6322        buffer_start.row..buffer_end.row + 1
 6323    }
 6324}
 6325
 6326impl<T: InvalidationRegion> InvalidationStack<T> {
 6327    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6328    where
 6329        S: Clone + ToOffset,
 6330    {
 6331        while let Some(region) = self.last() {
 6332            let all_selections_inside_invalidation_ranges =
 6333                if selections.len() == region.ranges().len() {
 6334                    selections
 6335                        .iter()
 6336                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6337                        .all(|(selection, invalidation_range)| {
 6338                            let head = selection.head().to_offset(&buffer);
 6339                            invalidation_range.start <= head && invalidation_range.end >= head
 6340                        })
 6341                } else {
 6342                    false
 6343                };
 6344
 6345            if all_selections_inside_invalidation_ranges {
 6346                break;
 6347            } else {
 6348                self.pop();
 6349            }
 6350        }
 6351    }
 6352}
 6353
 6354impl<T> Default for InvalidationStack<T> {
 6355    fn default() -> Self {
 6356        Self(Default::default())
 6357    }
 6358}
 6359
 6360impl<T> Deref for InvalidationStack<T> {
 6361    type Target = Vec<T>;
 6362
 6363    fn deref(&self) -> &Self::Target {
 6364        &self.0
 6365    }
 6366}
 6367
 6368impl<T> DerefMut for InvalidationStack<T> {
 6369    fn deref_mut(&mut self) -> &mut Self::Target {
 6370        &mut self.0
 6371    }
 6372}
 6373
 6374impl InvalidationRegion for BracketPairState {
 6375    fn ranges(&self) -> &[Range<Anchor>] {
 6376        &self.ranges
 6377    }
 6378}
 6379
 6380impl InvalidationRegion for SnippetState {
 6381    fn ranges(&self) -> &[Range<Anchor>] {
 6382        &self.ranges[self.active_index]
 6383    }
 6384}
 6385
 6386impl Deref for EditorStyle {
 6387    type Target = theme::Editor;
 6388
 6389    fn deref(&self) -> &Self::Target {
 6390        &self.theme
 6391    }
 6392}
 6393
 6394pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6395    let mut highlighted_lines = Vec::new();
 6396    for line in diagnostic.message.lines() {
 6397        highlighted_lines.push(highlight_diagnostic_message(line));
 6398    }
 6399
 6400    Arc::new(move |cx: &mut BlockContext| {
 6401        let settings = cx.global::<Settings>();
 6402        let theme = &settings.theme.editor;
 6403        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6404        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6405        Flex::column()
 6406            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6407                Label::new(
 6408                    line.clone(),
 6409                    style.message.clone().with_font_size(font_size),
 6410                )
 6411                .with_highlights(highlights.clone())
 6412                .contained()
 6413                .with_margin_left(cx.anchor_x)
 6414                .boxed()
 6415            }))
 6416            .aligned()
 6417            .left()
 6418            .boxed()
 6419    })
 6420}
 6421
 6422pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6423    let mut message_without_backticks = String::new();
 6424    let mut prev_offset = 0;
 6425    let mut inside_block = false;
 6426    let mut highlights = Vec::new();
 6427    for (match_ix, (offset, _)) in message
 6428        .match_indices('`')
 6429        .chain([(message.len(), "")])
 6430        .enumerate()
 6431    {
 6432        message_without_backticks.push_str(&message[prev_offset..offset]);
 6433        if inside_block {
 6434            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6435        }
 6436
 6437        inside_block = !inside_block;
 6438        prev_offset = offset + 1;
 6439    }
 6440
 6441    (message_without_backticks, highlights)
 6442}
 6443
 6444pub fn diagnostic_style(
 6445    severity: DiagnosticSeverity,
 6446    valid: bool,
 6447    theme: &theme::Editor,
 6448) -> DiagnosticStyle {
 6449    match (severity, valid) {
 6450        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6451        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6452        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6453        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6454        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6455        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6456        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6457        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6458        _ => theme.invalid_hint_diagnostic.clone(),
 6459    }
 6460}
 6461
 6462pub fn combine_syntax_and_fuzzy_match_highlights(
 6463    text: &str,
 6464    default_style: HighlightStyle,
 6465    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6466    match_indices: &[usize],
 6467) -> Vec<(Range<usize>, HighlightStyle)> {
 6468    let mut result = Vec::new();
 6469    let mut match_indices = match_indices.iter().copied().peekable();
 6470
 6471    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6472    {
 6473        syntax_highlight.weight = None;
 6474
 6475        // Add highlights for any fuzzy match characters before the next
 6476        // syntax highlight range.
 6477        while let Some(&match_index) = match_indices.peek() {
 6478            if match_index >= range.start {
 6479                break;
 6480            }
 6481            match_indices.next();
 6482            let end_index = char_ix_after(match_index, text);
 6483            let mut match_style = default_style;
 6484            match_style.weight = Some(fonts::Weight::BOLD);
 6485            result.push((match_index..end_index, match_style));
 6486        }
 6487
 6488        if range.start == usize::MAX {
 6489            break;
 6490        }
 6491
 6492        // Add highlights for any fuzzy match characters within the
 6493        // syntax highlight range.
 6494        let mut offset = range.start;
 6495        while let Some(&match_index) = match_indices.peek() {
 6496            if match_index >= range.end {
 6497                break;
 6498            }
 6499
 6500            match_indices.next();
 6501            if match_index > offset {
 6502                result.push((offset..match_index, syntax_highlight));
 6503            }
 6504
 6505            let mut end_index = char_ix_after(match_index, text);
 6506            while let Some(&next_match_index) = match_indices.peek() {
 6507                if next_match_index == end_index && next_match_index < range.end {
 6508                    end_index = char_ix_after(next_match_index, text);
 6509                    match_indices.next();
 6510                } else {
 6511                    break;
 6512                }
 6513            }
 6514
 6515            let mut match_style = syntax_highlight;
 6516            match_style.weight = Some(fonts::Weight::BOLD);
 6517            result.push((match_index..end_index, match_style));
 6518            offset = end_index;
 6519        }
 6520
 6521        if offset < range.end {
 6522            result.push((offset..range.end, syntax_highlight));
 6523        }
 6524    }
 6525
 6526    fn char_ix_after(ix: usize, text: &str) -> usize {
 6527        ix + text[ix..].chars().next().unwrap().len_utf8()
 6528    }
 6529
 6530    result
 6531}
 6532
 6533pub fn styled_runs_for_code_label<'a>(
 6534    label: &'a CodeLabel,
 6535    syntax_theme: &'a theme::SyntaxTheme,
 6536) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6537    let fade_out = HighlightStyle {
 6538        fade_out: Some(0.35),
 6539        ..Default::default()
 6540    };
 6541
 6542    let mut prev_end = label.filter_range.end;
 6543    label
 6544        .runs
 6545        .iter()
 6546        .enumerate()
 6547        .flat_map(move |(ix, (range, highlight_id))| {
 6548            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6549                style
 6550            } else {
 6551                return Default::default();
 6552            };
 6553            let mut muted_style = style.clone();
 6554            muted_style.highlight(fade_out);
 6555
 6556            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6557            if range.start >= label.filter_range.end {
 6558                if range.start > prev_end {
 6559                    runs.push((prev_end..range.start, fade_out));
 6560                }
 6561                runs.push((range.clone(), muted_style));
 6562            } else if range.end <= label.filter_range.end {
 6563                runs.push((range.clone(), style));
 6564            } else {
 6565                runs.push((range.start..label.filter_range.end, style));
 6566                runs.push((label.filter_range.end..range.end, muted_style));
 6567            }
 6568            prev_end = cmp::max(prev_end, range.end);
 6569
 6570            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6571                runs.push((prev_end..label.text.len(), fade_out));
 6572            }
 6573
 6574            runs
 6575        })
 6576}
 6577
 6578#[cfg(test)]
 6579mod tests {
 6580    use crate::test::{
 6581        assert_text_with_selections, build_editor, select_ranges, EditorLspTestContext,
 6582        EditorTestContext,
 6583    };
 6584
 6585    use super::*;
 6586    use futures::StreamExt;
 6587    use gpui::{
 6588        geometry::rect::RectF,
 6589        platform::{WindowBounds, WindowOptions},
 6590    };
 6591    use indoc::indoc;
 6592    use language::{FakeLspAdapter, LanguageConfig};
 6593    use project::FakeFs;
 6594    use settings::EditorSettings;
 6595    use std::{cell::RefCell, rc::Rc, time::Instant};
 6596    use text::Point;
 6597    use unindent::Unindent;
 6598    use util::{
 6599        assert_set_eq,
 6600        test::{
 6601            marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker,
 6602        },
 6603    };
 6604    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6605
 6606    #[gpui::test]
 6607    fn test_edit_events(cx: &mut MutableAppContext) {
 6608        cx.set_global(Settings::test(cx));
 6609        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6610
 6611        let events = Rc::new(RefCell::new(Vec::new()));
 6612        let (_, editor1) = cx.add_window(Default::default(), {
 6613            let events = events.clone();
 6614            |cx| {
 6615                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6616                    if matches!(
 6617                        event,
 6618                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6619                    ) {
 6620                        events.borrow_mut().push(("editor1", *event));
 6621                    }
 6622                })
 6623                .detach();
 6624                Editor::for_buffer(buffer.clone(), None, cx)
 6625            }
 6626        });
 6627        let (_, editor2) = cx.add_window(Default::default(), {
 6628            let events = events.clone();
 6629            |cx| {
 6630                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6631                    if matches!(
 6632                        event,
 6633                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6634                    ) {
 6635                        events.borrow_mut().push(("editor2", *event));
 6636                    }
 6637                })
 6638                .detach();
 6639                Editor::for_buffer(buffer.clone(), None, cx)
 6640            }
 6641        });
 6642        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6643
 6644        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6645        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6646        assert_eq!(
 6647            mem::take(&mut *events.borrow_mut()),
 6648            [
 6649                ("editor1", Event::Edited),
 6650                ("editor1", Event::BufferEdited),
 6651                ("editor2", Event::BufferEdited),
 6652                ("editor1", Event::DirtyChanged),
 6653                ("editor2", Event::DirtyChanged)
 6654            ]
 6655        );
 6656
 6657        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6658        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6659        assert_eq!(
 6660            mem::take(&mut *events.borrow_mut()),
 6661            [
 6662                ("editor2", Event::Edited),
 6663                ("editor1", Event::BufferEdited),
 6664                ("editor2", Event::BufferEdited),
 6665            ]
 6666        );
 6667
 6668        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6669        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6670        assert_eq!(
 6671            mem::take(&mut *events.borrow_mut()),
 6672            [
 6673                ("editor1", Event::Edited),
 6674                ("editor1", Event::BufferEdited),
 6675                ("editor2", Event::BufferEdited),
 6676                ("editor1", Event::DirtyChanged),
 6677                ("editor2", Event::DirtyChanged),
 6678            ]
 6679        );
 6680
 6681        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6682        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6683        assert_eq!(
 6684            mem::take(&mut *events.borrow_mut()),
 6685            [
 6686                ("editor1", Event::Edited),
 6687                ("editor1", Event::BufferEdited),
 6688                ("editor2", Event::BufferEdited),
 6689                ("editor1", Event::DirtyChanged),
 6690                ("editor2", Event::DirtyChanged),
 6691            ]
 6692        );
 6693
 6694        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6695        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6696        assert_eq!(
 6697            mem::take(&mut *events.borrow_mut()),
 6698            [
 6699                ("editor2", Event::Edited),
 6700                ("editor1", Event::BufferEdited),
 6701                ("editor2", Event::BufferEdited),
 6702                ("editor1", Event::DirtyChanged),
 6703                ("editor2", Event::DirtyChanged),
 6704            ]
 6705        );
 6706
 6707        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6708        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6709        assert_eq!(
 6710            mem::take(&mut *events.borrow_mut()),
 6711            [
 6712                ("editor2", Event::Edited),
 6713                ("editor1", Event::BufferEdited),
 6714                ("editor2", Event::BufferEdited),
 6715                ("editor1", Event::DirtyChanged),
 6716                ("editor2", Event::DirtyChanged),
 6717            ]
 6718        );
 6719
 6720        // No event is emitted when the mutation is a no-op.
 6721        editor2.update(cx, |editor, cx| {
 6722            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6723
 6724            editor.backspace(&Backspace, cx);
 6725        });
 6726        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6727    }
 6728
 6729    #[gpui::test]
 6730    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6731        cx.set_global(Settings::test(cx));
 6732        let mut now = Instant::now();
 6733        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6734        let group_interval = buffer.read(cx).transaction_group_interval();
 6735        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6736        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6737
 6738        editor.update(cx, |editor, cx| {
 6739            editor.start_transaction_at(now, cx);
 6740            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6741
 6742            editor.insert("cd", cx);
 6743            editor.end_transaction_at(now, cx);
 6744            assert_eq!(editor.text(cx), "12cd56");
 6745            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6746
 6747            editor.start_transaction_at(now, cx);
 6748            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6749            editor.insert("e", cx);
 6750            editor.end_transaction_at(now, cx);
 6751            assert_eq!(editor.text(cx), "12cde6");
 6752            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6753
 6754            now += group_interval + Duration::from_millis(1);
 6755            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6756
 6757            // Simulate an edit in another editor
 6758            buffer.update(cx, |buffer, cx| {
 6759                buffer.start_transaction_at(now, cx);
 6760                buffer.edit([(0..1, "a")], None, cx);
 6761                buffer.edit([(1..1, "b")], None, cx);
 6762                buffer.end_transaction_at(now, cx);
 6763            });
 6764
 6765            assert_eq!(editor.text(cx), "ab2cde6");
 6766            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6767
 6768            // Last transaction happened past the group interval in a different editor.
 6769            // Undo it individually and don't restore selections.
 6770            editor.undo(&Undo, cx);
 6771            assert_eq!(editor.text(cx), "12cde6");
 6772            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6773
 6774            // First two transactions happened within the group interval in this editor.
 6775            // Undo them together and restore selections.
 6776            editor.undo(&Undo, cx);
 6777            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6778            assert_eq!(editor.text(cx), "123456");
 6779            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6780
 6781            // Redo the first two transactions together.
 6782            editor.redo(&Redo, cx);
 6783            assert_eq!(editor.text(cx), "12cde6");
 6784            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6785
 6786            // Redo the last transaction on its own.
 6787            editor.redo(&Redo, cx);
 6788            assert_eq!(editor.text(cx), "ab2cde6");
 6789            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6790
 6791            // Test empty transactions.
 6792            editor.start_transaction_at(now, cx);
 6793            editor.end_transaction_at(now, cx);
 6794            editor.undo(&Undo, cx);
 6795            assert_eq!(editor.text(cx), "12cde6");
 6796        });
 6797    }
 6798
 6799    #[gpui::test]
 6800    fn test_ime_composition(cx: &mut MutableAppContext) {
 6801        cx.set_global(Settings::test(cx));
 6802        let buffer = cx.add_model(|cx| {
 6803            let mut buffer = language::Buffer::new(0, "abcde", cx);
 6804            // Ensure automatic grouping doesn't occur.
 6805            buffer.set_group_interval(Duration::ZERO);
 6806            buffer
 6807        });
 6808
 6809        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6810        cx.add_window(Default::default(), |cx| {
 6811            let mut editor = build_editor(buffer.clone(), cx);
 6812
 6813            // Start a new IME composition.
 6814            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6815            editor.replace_and_mark_text_in_range(Some(0..1), "á", None, cx);
 6816            editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
 6817            assert_eq!(editor.text(cx), "äbcde");
 6818            assert_eq!(
 6819                editor.marked_text_ranges(cx),
 6820                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6821            );
 6822
 6823            // Finalize IME composition.
 6824            editor.replace_text_in_range(None, "ā", cx);
 6825            assert_eq!(editor.text(cx), "ābcde");
 6826            assert_eq!(editor.marked_text_ranges(cx), None);
 6827
 6828            // IME composition edits are grouped and are undone/redone at once.
 6829            editor.undo(&Default::default(), cx);
 6830            assert_eq!(editor.text(cx), "abcde");
 6831            assert_eq!(editor.marked_text_ranges(cx), None);
 6832            editor.redo(&Default::default(), cx);
 6833            assert_eq!(editor.text(cx), "ābcde");
 6834            assert_eq!(editor.marked_text_ranges(cx), None);
 6835
 6836            // Start a new IME composition.
 6837            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6838            assert_eq!(
 6839                editor.marked_text_ranges(cx),
 6840                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6841            );
 6842
 6843            // Undoing during an IME composition cancels it.
 6844            editor.undo(&Default::default(), cx);
 6845            assert_eq!(editor.text(cx), "ābcde");
 6846            assert_eq!(editor.marked_text_ranges(cx), None);
 6847
 6848            // Start a new IME composition with an invalid marked range, ensuring it gets clipped.
 6849            editor.replace_and_mark_text_in_range(Some(4..999), "è", None, cx);
 6850            assert_eq!(editor.text(cx), "ābcdè");
 6851            assert_eq!(
 6852                editor.marked_text_ranges(cx),
 6853                Some(vec![OffsetUtf16(4)..OffsetUtf16(5)])
 6854            );
 6855
 6856            // Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
 6857            editor.replace_text_in_range(Some(4..999), "ę", cx);
 6858            assert_eq!(editor.text(cx), "ābcdę");
 6859            assert_eq!(editor.marked_text_ranges(cx), None);
 6860
 6861            // Start a new IME composition with multiple cursors.
 6862            editor.change_selections(None, cx, |s| {
 6863                s.select_ranges([
 6864                    OffsetUtf16(1)..OffsetUtf16(1),
 6865                    OffsetUtf16(3)..OffsetUtf16(3),
 6866                    OffsetUtf16(5)..OffsetUtf16(5),
 6867                ])
 6868            });
 6869            editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, cx);
 6870            assert_eq!(editor.text(cx), "XYZbXYZdXYZ");
 6871            assert_eq!(
 6872                editor.marked_text_ranges(cx),
 6873                Some(vec![
 6874                    OffsetUtf16(0)..OffsetUtf16(3),
 6875                    OffsetUtf16(4)..OffsetUtf16(7),
 6876                    OffsetUtf16(8)..OffsetUtf16(11)
 6877                ])
 6878            );
 6879
 6880            // Ensure the newly-marked range gets treated as relative to the previously-marked ranges.
 6881            editor.replace_and_mark_text_in_range(Some(1..2), "1", None, cx);
 6882            assert_eq!(editor.text(cx), "X1ZbX1ZdX1Z");
 6883            assert_eq!(
 6884                editor.marked_text_ranges(cx),
 6885                Some(vec![
 6886                    OffsetUtf16(1)..OffsetUtf16(2),
 6887                    OffsetUtf16(5)..OffsetUtf16(6),
 6888                    OffsetUtf16(9)..OffsetUtf16(10)
 6889                ])
 6890            );
 6891
 6892            // Finalize IME composition with multiple cursors.
 6893            editor.replace_text_in_range(Some(9..10), "2", cx);
 6894            assert_eq!(editor.text(cx), "X2ZbX2ZdX2Z");
 6895            assert_eq!(editor.marked_text_ranges(cx), None);
 6896
 6897            editor
 6898        });
 6899    }
 6900
 6901    #[gpui::test]
 6902    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6903        cx.set_global(Settings::test(cx));
 6904
 6905        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6906        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6907        editor.update(cx, |view, cx| {
 6908            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6909        });
 6910        assert_eq!(
 6911            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6912            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6913        );
 6914
 6915        editor.update(cx, |view, cx| {
 6916            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6917        });
 6918
 6919        assert_eq!(
 6920            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6921            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6922        );
 6923
 6924        editor.update(cx, |view, cx| {
 6925            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6926        });
 6927
 6928        assert_eq!(
 6929            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6930            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6931        );
 6932
 6933        editor.update(cx, |view, cx| {
 6934            view.end_selection(cx);
 6935            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6936        });
 6937
 6938        assert_eq!(
 6939            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6940            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6941        );
 6942
 6943        editor.update(cx, |view, cx| {
 6944            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6945            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6946        });
 6947
 6948        assert_eq!(
 6949            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6950            [
 6951                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6952                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6953            ]
 6954        );
 6955
 6956        editor.update(cx, |view, cx| {
 6957            view.end_selection(cx);
 6958        });
 6959
 6960        assert_eq!(
 6961            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6962            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6963        );
 6964    }
 6965
 6966    #[gpui::test]
 6967    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6968        cx.set_global(Settings::test(cx));
 6969        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6970        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6971
 6972        view.update(cx, |view, cx| {
 6973            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6974            assert_eq!(
 6975                view.selections.display_ranges(cx),
 6976                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6977            );
 6978        });
 6979
 6980        view.update(cx, |view, cx| {
 6981            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6982            assert_eq!(
 6983                view.selections.display_ranges(cx),
 6984                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6985            );
 6986        });
 6987
 6988        view.update(cx, |view, cx| {
 6989            view.cancel(&Cancel, cx);
 6990            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6991            assert_eq!(
 6992                view.selections.display_ranges(cx),
 6993                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6994            );
 6995        });
 6996    }
 6997
 6998    #[gpui::test]
 6999    fn test_clone(cx: &mut gpui::MutableAppContext) {
 7000        let (text, selection_ranges) = marked_text_ranges(indoc! {"
 7001            one
 7002            two
 7003            three[]
 7004            four
 7005            five[]
 7006        "});
 7007        cx.set_global(Settings::test(cx));
 7008        let buffer = MultiBuffer::build_simple(&text, cx);
 7009
 7010        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7011
 7012        editor.update(cx, |editor, cx| {
 7013            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 7014            editor.fold_ranges(
 7015                [
 7016                    Point::new(1, 0)..Point::new(2, 0),
 7017                    Point::new(3, 0)..Point::new(4, 0),
 7018                ],
 7019                cx,
 7020            );
 7021        });
 7022
 7023        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 7024            cx.add_window(Default::default(), |cx| editor.clone(cx))
 7025        });
 7026
 7027        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 7028        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 7029
 7030        assert_eq!(
 7031            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 7032            editor.update(cx, |e, cx| e.display_text(cx))
 7033        );
 7034        assert_eq!(
 7035            cloned_snapshot
 7036                .folds_in_range(0..text.len())
 7037                .collect::<Vec<_>>(),
 7038            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 7039        );
 7040        assert_set_eq!(
 7041            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 7042            editor.read(cx).selections.ranges(cx)
 7043        );
 7044        assert_set_eq!(
 7045            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 7046            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 7047        );
 7048    }
 7049
 7050    #[gpui::test]
 7051    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 7052        cx.set_global(Settings::test(cx));
 7053        use workspace::Item;
 7054        let pane = cx.add_view(Default::default(), |cx| Pane::new(cx));
 7055        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 7056
 7057        cx.add_window(Default::default(), |cx| {
 7058            let mut editor = build_editor(buffer.clone(), cx);
 7059            let handle = cx.handle();
 7060            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 7061
 7062            fn pop_history(
 7063                editor: &mut Editor,
 7064                cx: &mut MutableAppContext,
 7065            ) -> Option<NavigationEntry> {
 7066                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 7067            }
 7068
 7069            // Move the cursor a small distance.
 7070            // Nothing is added to the navigation history.
 7071            editor.change_selections(None, cx, |s| {
 7072                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 7073            });
 7074            editor.change_selections(None, cx, |s| {
 7075                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 7076            });
 7077            assert!(pop_history(&mut editor, cx).is_none());
 7078
 7079            // Move the cursor a large distance.
 7080            // The history can jump back to the previous position.
 7081            editor.change_selections(None, cx, |s| {
 7082                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 7083            });
 7084            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7085            editor.navigate(nav_entry.data.unwrap(), cx);
 7086            assert_eq!(nav_entry.item.id(), cx.view_id());
 7087            assert_eq!(
 7088                editor.selections.display_ranges(cx),
 7089                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 7090            );
 7091            assert!(pop_history(&mut editor, cx).is_none());
 7092
 7093            // Move the cursor a small distance via the mouse.
 7094            // Nothing is added to the navigation history.
 7095            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 7096            editor.end_selection(cx);
 7097            assert_eq!(
 7098                editor.selections.display_ranges(cx),
 7099                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7100            );
 7101            assert!(pop_history(&mut editor, cx).is_none());
 7102
 7103            // Move the cursor a large distance via the mouse.
 7104            // The history can jump back to the previous position.
 7105            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 7106            editor.end_selection(cx);
 7107            assert_eq!(
 7108                editor.selections.display_ranges(cx),
 7109                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 7110            );
 7111            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7112            editor.navigate(nav_entry.data.unwrap(), cx);
 7113            assert_eq!(nav_entry.item.id(), cx.view_id());
 7114            assert_eq!(
 7115                editor.selections.display_ranges(cx),
 7116                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7117            );
 7118            assert!(pop_history(&mut editor, cx).is_none());
 7119
 7120            // Set scroll position to check later
 7121            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 7122            let original_scroll_position = editor.scroll_position;
 7123            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 7124
 7125            // Jump to the end of the document and adjust scroll
 7126            editor.move_to_end(&MoveToEnd, cx);
 7127            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 7128            assert_ne!(editor.scroll_position, original_scroll_position);
 7129            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7130
 7131            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7132            editor.navigate(nav_entry.data.unwrap(), cx);
 7133            assert_eq!(editor.scroll_position, original_scroll_position);
 7134            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7135
 7136            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 7137            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 7138            invalid_anchor.text_anchor.buffer_id = Some(999);
 7139            let invalid_point = Point::new(9999, 0);
 7140            editor.navigate(
 7141                Box::new(NavigationData {
 7142                    cursor_anchor: invalid_anchor.clone(),
 7143                    cursor_position: invalid_point,
 7144                    scroll_top_anchor: invalid_anchor.clone(),
 7145                    scroll_top_row: invalid_point.row,
 7146                    scroll_position: Default::default(),
 7147                }),
 7148                cx,
 7149            );
 7150            assert_eq!(
 7151                editor.selections.display_ranges(cx),
 7152                &[editor.max_point(cx)..editor.max_point(cx)]
 7153            );
 7154            assert_eq!(
 7155                editor.scroll_position(cx),
 7156                vec2f(0., editor.max_point(cx).row() as f32)
 7157            );
 7158
 7159            editor
 7160        });
 7161    }
 7162
 7163    #[gpui::test]
 7164    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 7165        cx.set_global(Settings::test(cx));
 7166        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7167        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7168
 7169        view.update(cx, |view, cx| {
 7170            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 7171            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7172            view.end_selection(cx);
 7173
 7174            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 7175            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 7176            view.end_selection(cx);
 7177            assert_eq!(
 7178                view.selections.display_ranges(cx),
 7179                [
 7180                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 7181                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 7182                ]
 7183            );
 7184        });
 7185
 7186        view.update(cx, |view, cx| {
 7187            view.cancel(&Cancel, cx);
 7188            assert_eq!(
 7189                view.selections.display_ranges(cx),
 7190                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 7191            );
 7192        });
 7193
 7194        view.update(cx, |view, cx| {
 7195            view.cancel(&Cancel, cx);
 7196            assert_eq!(
 7197                view.selections.display_ranges(cx),
 7198                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 7199            );
 7200        });
 7201    }
 7202
 7203    #[gpui::test]
 7204    fn test_fold(cx: &mut gpui::MutableAppContext) {
 7205        cx.set_global(Settings::test(cx));
 7206        let buffer = MultiBuffer::build_simple(
 7207            &"
 7208                impl Foo {
 7209                    // Hello!
 7210
 7211                    fn a() {
 7212                        1
 7213                    }
 7214
 7215                    fn b() {
 7216                        2
 7217                    }
 7218
 7219                    fn c() {
 7220                        3
 7221                    }
 7222                }
 7223            "
 7224            .unindent(),
 7225            cx,
 7226        );
 7227        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7228
 7229        view.update(cx, |view, cx| {
 7230            view.change_selections(None, cx, |s| {
 7231                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 7232            });
 7233            view.fold(&Fold, cx);
 7234            assert_eq!(
 7235                view.display_text(cx),
 7236                "
 7237                    impl Foo {
 7238                        // Hello!
 7239
 7240                        fn a() {
 7241                            1
 7242                        }
 7243
 7244                        fn b() {…
 7245                        }
 7246
 7247                        fn c() {…
 7248                        }
 7249                    }
 7250                "
 7251                .unindent(),
 7252            );
 7253
 7254            view.fold(&Fold, cx);
 7255            assert_eq!(
 7256                view.display_text(cx),
 7257                "
 7258                    impl Foo {…
 7259                    }
 7260                "
 7261                .unindent(),
 7262            );
 7263
 7264            view.unfold_lines(&UnfoldLines, cx);
 7265            assert_eq!(
 7266                view.display_text(cx),
 7267                "
 7268                    impl Foo {
 7269                        // Hello!
 7270
 7271                        fn a() {
 7272                            1
 7273                        }
 7274
 7275                        fn b() {…
 7276                        }
 7277
 7278                        fn c() {…
 7279                        }
 7280                    }
 7281                "
 7282                .unindent(),
 7283            );
 7284
 7285            view.unfold_lines(&UnfoldLines, cx);
 7286            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7287        });
 7288    }
 7289
 7290    #[gpui::test]
 7291    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7292        cx.set_global(Settings::test(cx));
 7293        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7294        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7295
 7296        buffer.update(cx, |buffer, cx| {
 7297            buffer.edit(
 7298                vec![
 7299                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7300                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7301                ],
 7302                None,
 7303                cx,
 7304            );
 7305        });
 7306
 7307        view.update(cx, |view, cx| {
 7308            assert_eq!(
 7309                view.selections.display_ranges(cx),
 7310                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7311            );
 7312
 7313            view.move_down(&MoveDown, cx);
 7314            assert_eq!(
 7315                view.selections.display_ranges(cx),
 7316                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7317            );
 7318
 7319            view.move_right(&MoveRight, cx);
 7320            assert_eq!(
 7321                view.selections.display_ranges(cx),
 7322                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7323            );
 7324
 7325            view.move_left(&MoveLeft, cx);
 7326            assert_eq!(
 7327                view.selections.display_ranges(cx),
 7328                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7329            );
 7330
 7331            view.move_up(&MoveUp, cx);
 7332            assert_eq!(
 7333                view.selections.display_ranges(cx),
 7334                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7335            );
 7336
 7337            view.move_to_end(&MoveToEnd, cx);
 7338            assert_eq!(
 7339                view.selections.display_ranges(cx),
 7340                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7341            );
 7342
 7343            view.move_to_beginning(&MoveToBeginning, cx);
 7344            assert_eq!(
 7345                view.selections.display_ranges(cx),
 7346                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7347            );
 7348
 7349            view.change_selections(None, cx, |s| {
 7350                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 7351            });
 7352            view.select_to_beginning(&SelectToBeginning, cx);
 7353            assert_eq!(
 7354                view.selections.display_ranges(cx),
 7355                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7356            );
 7357
 7358            view.select_to_end(&SelectToEnd, cx);
 7359            assert_eq!(
 7360                view.selections.display_ranges(cx),
 7361                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7362            );
 7363        });
 7364    }
 7365
 7366    #[gpui::test]
 7367    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7368        cx.set_global(Settings::test(cx));
 7369        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7370        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7371
 7372        assert_eq!('ⓐ'.len_utf8(), 3);
 7373        assert_eq!('α'.len_utf8(), 2);
 7374
 7375        view.update(cx, |view, cx| {
 7376            view.fold_ranges(
 7377                vec![
 7378                    Point::new(0, 6)..Point::new(0, 12),
 7379                    Point::new(1, 2)..Point::new(1, 4),
 7380                    Point::new(2, 4)..Point::new(2, 8),
 7381                ],
 7382                cx,
 7383            );
 7384            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7385
 7386            view.move_right(&MoveRight, cx);
 7387            assert_eq!(
 7388                view.selections.display_ranges(cx),
 7389                &[empty_range(0, "".len())]
 7390            );
 7391            view.move_right(&MoveRight, cx);
 7392            assert_eq!(
 7393                view.selections.display_ranges(cx),
 7394                &[empty_range(0, "ⓐⓑ".len())]
 7395            );
 7396            view.move_right(&MoveRight, cx);
 7397            assert_eq!(
 7398                view.selections.display_ranges(cx),
 7399                &[empty_range(0, "ⓐⓑ…".len())]
 7400            );
 7401
 7402            view.move_down(&MoveDown, cx);
 7403            assert_eq!(
 7404                view.selections.display_ranges(cx),
 7405                &[empty_range(1, "ab…".len())]
 7406            );
 7407            view.move_left(&MoveLeft, cx);
 7408            assert_eq!(
 7409                view.selections.display_ranges(cx),
 7410                &[empty_range(1, "ab".len())]
 7411            );
 7412            view.move_left(&MoveLeft, cx);
 7413            assert_eq!(
 7414                view.selections.display_ranges(cx),
 7415                &[empty_range(1, "a".len())]
 7416            );
 7417
 7418            view.move_down(&MoveDown, cx);
 7419            assert_eq!(
 7420                view.selections.display_ranges(cx),
 7421                &[empty_range(2, "α".len())]
 7422            );
 7423            view.move_right(&MoveRight, cx);
 7424            assert_eq!(
 7425                view.selections.display_ranges(cx),
 7426                &[empty_range(2, "αβ".len())]
 7427            );
 7428            view.move_right(&MoveRight, cx);
 7429            assert_eq!(
 7430                view.selections.display_ranges(cx),
 7431                &[empty_range(2, "αβ…".len())]
 7432            );
 7433            view.move_right(&MoveRight, cx);
 7434            assert_eq!(
 7435                view.selections.display_ranges(cx),
 7436                &[empty_range(2, "αβ…ε".len())]
 7437            );
 7438
 7439            view.move_up(&MoveUp, cx);
 7440            assert_eq!(
 7441                view.selections.display_ranges(cx),
 7442                &[empty_range(1, "ab…e".len())]
 7443            );
 7444            view.move_up(&MoveUp, cx);
 7445            assert_eq!(
 7446                view.selections.display_ranges(cx),
 7447                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7448            );
 7449            view.move_left(&MoveLeft, cx);
 7450            assert_eq!(
 7451                view.selections.display_ranges(cx),
 7452                &[empty_range(0, "ⓐⓑ…".len())]
 7453            );
 7454            view.move_left(&MoveLeft, cx);
 7455            assert_eq!(
 7456                view.selections.display_ranges(cx),
 7457                &[empty_range(0, "ⓐⓑ".len())]
 7458            );
 7459            view.move_left(&MoveLeft, cx);
 7460            assert_eq!(
 7461                view.selections.display_ranges(cx),
 7462                &[empty_range(0, "".len())]
 7463            );
 7464        });
 7465    }
 7466
 7467    #[gpui::test]
 7468    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7469        cx.set_global(Settings::test(cx));
 7470        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7471        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7472        view.update(cx, |view, cx| {
 7473            view.change_selections(None, cx, |s| {
 7474                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7475            });
 7476            view.move_down(&MoveDown, cx);
 7477            assert_eq!(
 7478                view.selections.display_ranges(cx),
 7479                &[empty_range(1, "abcd".len())]
 7480            );
 7481
 7482            view.move_down(&MoveDown, cx);
 7483            assert_eq!(
 7484                view.selections.display_ranges(cx),
 7485                &[empty_range(2, "αβγ".len())]
 7486            );
 7487
 7488            view.move_down(&MoveDown, cx);
 7489            assert_eq!(
 7490                view.selections.display_ranges(cx),
 7491                &[empty_range(3, "abcd".len())]
 7492            );
 7493
 7494            view.move_down(&MoveDown, cx);
 7495            assert_eq!(
 7496                view.selections.display_ranges(cx),
 7497                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7498            );
 7499
 7500            view.move_up(&MoveUp, cx);
 7501            assert_eq!(
 7502                view.selections.display_ranges(cx),
 7503                &[empty_range(3, "abcd".len())]
 7504            );
 7505
 7506            view.move_up(&MoveUp, cx);
 7507            assert_eq!(
 7508                view.selections.display_ranges(cx),
 7509                &[empty_range(2, "αβγ".len())]
 7510            );
 7511        });
 7512    }
 7513
 7514    #[gpui::test]
 7515    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7516        cx.set_global(Settings::test(cx));
 7517        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7518        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7519        view.update(cx, |view, cx| {
 7520            view.change_selections(None, cx, |s| {
 7521                s.select_display_ranges([
 7522                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7523                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7524                ]);
 7525            });
 7526        });
 7527
 7528        view.update(cx, |view, cx| {
 7529            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7530            assert_eq!(
 7531                view.selections.display_ranges(cx),
 7532                &[
 7533                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7534                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7535                ]
 7536            );
 7537        });
 7538
 7539        view.update(cx, |view, cx| {
 7540            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7541            assert_eq!(
 7542                view.selections.display_ranges(cx),
 7543                &[
 7544                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7545                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7546                ]
 7547            );
 7548        });
 7549
 7550        view.update(cx, |view, cx| {
 7551            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7552            assert_eq!(
 7553                view.selections.display_ranges(cx),
 7554                &[
 7555                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7556                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7557                ]
 7558            );
 7559        });
 7560
 7561        view.update(cx, |view, cx| {
 7562            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7563            assert_eq!(
 7564                view.selections.display_ranges(cx),
 7565                &[
 7566                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7567                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7568                ]
 7569            );
 7570        });
 7571
 7572        // Moving to the end of line again is a no-op.
 7573        view.update(cx, |view, cx| {
 7574            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7575            assert_eq!(
 7576                view.selections.display_ranges(cx),
 7577                &[
 7578                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7579                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7580                ]
 7581            );
 7582        });
 7583
 7584        view.update(cx, |view, cx| {
 7585            view.move_left(&MoveLeft, cx);
 7586            view.select_to_beginning_of_line(
 7587                &SelectToBeginningOfLine {
 7588                    stop_at_soft_wraps: true,
 7589                },
 7590                cx,
 7591            );
 7592            assert_eq!(
 7593                view.selections.display_ranges(cx),
 7594                &[
 7595                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7596                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7597                ]
 7598            );
 7599        });
 7600
 7601        view.update(cx, |view, cx| {
 7602            view.select_to_beginning_of_line(
 7603                &SelectToBeginningOfLine {
 7604                    stop_at_soft_wraps: true,
 7605                },
 7606                cx,
 7607            );
 7608            assert_eq!(
 7609                view.selections.display_ranges(cx),
 7610                &[
 7611                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7612                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7613                ]
 7614            );
 7615        });
 7616
 7617        view.update(cx, |view, cx| {
 7618            view.select_to_beginning_of_line(
 7619                &SelectToBeginningOfLine {
 7620                    stop_at_soft_wraps: true,
 7621                },
 7622                cx,
 7623            );
 7624            assert_eq!(
 7625                view.selections.display_ranges(cx),
 7626                &[
 7627                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7628                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7629                ]
 7630            );
 7631        });
 7632
 7633        view.update(cx, |view, cx| {
 7634            view.select_to_end_of_line(
 7635                &SelectToEndOfLine {
 7636                    stop_at_soft_wraps: true,
 7637                },
 7638                cx,
 7639            );
 7640            assert_eq!(
 7641                view.selections.display_ranges(cx),
 7642                &[
 7643                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7644                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7645                ]
 7646            );
 7647        });
 7648
 7649        view.update(cx, |view, cx| {
 7650            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7651            assert_eq!(view.display_text(cx), "ab\n  de");
 7652            assert_eq!(
 7653                view.selections.display_ranges(cx),
 7654                &[
 7655                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7656                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7657                ]
 7658            );
 7659        });
 7660
 7661        view.update(cx, |view, cx| {
 7662            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7663            assert_eq!(view.display_text(cx), "\n");
 7664            assert_eq!(
 7665                view.selections.display_ranges(cx),
 7666                &[
 7667                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7668                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7669                ]
 7670            );
 7671        });
 7672    }
 7673
 7674    #[gpui::test]
 7675    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7676        cx.set_global(Settings::test(cx));
 7677        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7678        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7679        view.update(cx, |view, cx| {
 7680            view.change_selections(None, cx, |s| {
 7681                s.select_display_ranges([
 7682                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7683                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7684                ])
 7685            });
 7686
 7687            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7688            assert_selection_ranges(
 7689                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7690                vec![('<', '>'), ('[', ']')],
 7691                view,
 7692                cx,
 7693            );
 7694
 7695            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7696            assert_selection_ranges(
 7697                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7698                vec![('<', '>'), ('[', ']')],
 7699                view,
 7700                cx,
 7701            );
 7702
 7703            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7704            assert_selection_ranges(
 7705                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7706                vec![('<', '>'), ('[', ']')],
 7707                view,
 7708                cx,
 7709            );
 7710
 7711            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7712            assert_selection_ranges(
 7713                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7714                vec![('<', '>'), ('[', ']')],
 7715                view,
 7716                cx,
 7717            );
 7718
 7719            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7720            assert_selection_ranges(
 7721                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7722                vec![('<', '>'), ('[', ']')],
 7723                view,
 7724                cx,
 7725            );
 7726
 7727            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7728            assert_selection_ranges(
 7729                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7730                vec![('<', '>'), ('[', ']')],
 7731                view,
 7732                cx,
 7733            );
 7734
 7735            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7736            assert_selection_ranges(
 7737                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7738                vec![('<', '>'), ('[', ']')],
 7739                view,
 7740                cx,
 7741            );
 7742
 7743            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7744            assert_selection_ranges(
 7745                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7746                vec![('<', '>'), ('[', ']')],
 7747                view,
 7748                cx,
 7749            );
 7750
 7751            view.move_right(&MoveRight, cx);
 7752            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7753            assert_selection_ranges(
 7754                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7755                vec![('<', '>'), ('[', ']')],
 7756                view,
 7757                cx,
 7758            );
 7759
 7760            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7761            assert_selection_ranges(
 7762                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7763                vec![('<', '>'), ('[', ']')],
 7764                view,
 7765                cx,
 7766            );
 7767
 7768            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7769            assert_selection_ranges(
 7770                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7771                vec![('<', '>'), ('[', ']')],
 7772                view,
 7773                cx,
 7774            );
 7775        });
 7776    }
 7777
 7778    #[gpui::test]
 7779    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7780        cx.set_global(Settings::test(cx));
 7781        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7782        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7783
 7784        view.update(cx, |view, cx| {
 7785            view.set_wrap_width(Some(140.), cx);
 7786            assert_eq!(
 7787                view.display_text(cx),
 7788                "use one::{\n    two::three::\n    four::five\n};"
 7789            );
 7790
 7791            view.change_selections(None, cx, |s| {
 7792                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7793            });
 7794
 7795            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7796            assert_eq!(
 7797                view.selections.display_ranges(cx),
 7798                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7799            );
 7800
 7801            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7802            assert_eq!(
 7803                view.selections.display_ranges(cx),
 7804                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7805            );
 7806
 7807            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7808            assert_eq!(
 7809                view.selections.display_ranges(cx),
 7810                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7811            );
 7812
 7813            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7814            assert_eq!(
 7815                view.selections.display_ranges(cx),
 7816                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7817            );
 7818
 7819            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7820            assert_eq!(
 7821                view.selections.display_ranges(cx),
 7822                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7823            );
 7824
 7825            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7826            assert_eq!(
 7827                view.selections.display_ranges(cx),
 7828                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7829            );
 7830        });
 7831    }
 7832
 7833    #[gpui::test]
 7834    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7835        cx.set_global(Settings::test(cx));
 7836        let (text, ranges) = marked_text_ranges("one [two three] four");
 7837        let buffer = MultiBuffer::build_simple(&text, cx);
 7838
 7839        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7840
 7841        editor.update(cx, |editor, cx| {
 7842            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
 7843            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7844            assert_eq!(editor.text(cx), " four");
 7845        });
 7846    }
 7847
 7848    #[gpui::test]
 7849    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7850        cx.set_global(Settings::test(cx));
 7851        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7852        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7853
 7854        view.update(cx, |view, cx| {
 7855            view.change_selections(None, cx, |s| {
 7856                s.select_display_ranges([
 7857                    // an empty selection - the preceding word fragment is deleted
 7858                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7859                    // characters selected - they are deleted
 7860                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7861                ])
 7862            });
 7863            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7864        });
 7865
 7866        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7867
 7868        view.update(cx, |view, cx| {
 7869            view.change_selections(None, cx, |s| {
 7870                s.select_display_ranges([
 7871                    // an empty selection - the following word fragment is deleted
 7872                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7873                    // characters selected - they are deleted
 7874                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7875                ])
 7876            });
 7877            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7878        });
 7879
 7880        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7881    }
 7882
 7883    #[gpui::test]
 7884    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7885        cx.set_global(Settings::test(cx));
 7886        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7887        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7888
 7889        view.update(cx, |view, cx| {
 7890            view.change_selections(None, cx, |s| {
 7891                s.select_display_ranges([
 7892                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7893                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7894                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7895                ])
 7896            });
 7897
 7898            view.newline(&Newline, cx);
 7899            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7900        });
 7901    }
 7902
 7903    #[gpui::test]
 7904    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7905        cx.set_global(Settings::test(cx));
 7906        let buffer = MultiBuffer::build_simple(
 7907            "
 7908                a
 7909                b(
 7910                    X
 7911                )
 7912                c(
 7913                    X
 7914                )
 7915            "
 7916            .unindent()
 7917            .as_str(),
 7918            cx,
 7919        );
 7920
 7921        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7922            let mut editor = build_editor(buffer.clone(), cx);
 7923            editor.change_selections(None, cx, |s| {
 7924                s.select_ranges([
 7925                    Point::new(2, 4)..Point::new(2, 5),
 7926                    Point::new(5, 4)..Point::new(5, 5),
 7927                ])
 7928            });
 7929            editor
 7930        });
 7931
 7932        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7933        buffer.update(cx, |buffer, cx| {
 7934            buffer.edit(
 7935                [
 7936                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7937                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7938                ],
 7939                None,
 7940                cx,
 7941            );
 7942            assert_eq!(
 7943                buffer.read(cx).text(),
 7944                "
 7945                    a
 7946                    b()
 7947                    c()
 7948                "
 7949                .unindent()
 7950            );
 7951        });
 7952
 7953        editor.update(cx, |editor, cx| {
 7954            assert_eq!(
 7955                editor.selections.ranges(cx),
 7956                &[
 7957                    Point::new(1, 2)..Point::new(1, 2),
 7958                    Point::new(2, 2)..Point::new(2, 2),
 7959                ],
 7960            );
 7961
 7962            editor.newline(&Newline, cx);
 7963            assert_eq!(
 7964                editor.text(cx),
 7965                "
 7966                    a
 7967                    b(
 7968                    )
 7969                    c(
 7970                    )
 7971                "
 7972                .unindent()
 7973            );
 7974
 7975            // The selections are moved after the inserted newlines
 7976            assert_eq!(
 7977                editor.selections.ranges(cx),
 7978                &[
 7979                    Point::new(2, 0)..Point::new(2, 0),
 7980                    Point::new(4, 0)..Point::new(4, 0),
 7981                ],
 7982            );
 7983        });
 7984    }
 7985
 7986    #[gpui::test]
 7987    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7988        cx.set_global(Settings::test(cx));
 7989        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7990        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7991            let mut editor = build_editor(buffer.clone(), cx);
 7992            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 7993            editor
 7994        });
 7995
 7996        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7997        buffer.update(cx, |buffer, cx| {
 7998            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
 7999            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 8000        });
 8001
 8002        editor.update(cx, |editor, cx| {
 8003            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 8004
 8005            editor.insert("Z", cx);
 8006            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 8007
 8008            // The selections are moved after the inserted characters
 8009            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 8010        });
 8011    }
 8012
 8013    #[gpui::test]
 8014    async fn test_tab(cx: &mut gpui::TestAppContext) {
 8015        let mut cx = EditorTestContext::new(cx).await;
 8016        cx.update(|cx| {
 8017            cx.update_global::<Settings, _, _>(|settings, _| {
 8018                settings.editor_overrides.tab_size = Some(NonZeroU32::new(3).unwrap());
 8019            });
 8020        });
 8021        cx.set_state(indoc! {"
 8022            |ab|c
 8023            |🏀|🏀|efg
 8024            d|
 8025        "});
 8026        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8027        cx.assert_editor_state(indoc! {"
 8028              |ab |c
 8029              |🏀  |🏀  |efg
 8030           d  |
 8031        "});
 8032
 8033        cx.set_state(indoc! {"
 8034            a
 8035            [🏀}🏀[🏀}🏀[🏀}
 8036        "});
 8037        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8038        cx.assert_editor_state(indoc! {"
 8039            a
 8040               [🏀}🏀[🏀}🏀[🏀}
 8041        "});
 8042    }
 8043
 8044    #[gpui::test]
 8045    async fn test_tab_on_blank_line_auto_indents(cx: &mut gpui::TestAppContext) {
 8046        let mut cx = EditorTestContext::new(cx).await;
 8047        let language = Arc::new(
 8048            Language::new(
 8049                LanguageConfig::default(),
 8050                Some(tree_sitter_rust::language()),
 8051            )
 8052            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 8053            .unwrap(),
 8054        );
 8055        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8056
 8057        // cursors that are already at the suggested indent level insert
 8058        // a soft tab. cursors that are to the left of the suggested indent
 8059        // auto-indent their line.
 8060        cx.set_state(indoc! {"
 8061            |
 8062            const a: B = (
 8063                c(
 8064                    d(
 8065            |
 8066                    )
 8067            |
 8068            |    )
 8069            );
 8070        "});
 8071        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8072        cx.assert_editor_state(indoc! {"
 8073                |
 8074            const a: B = (
 8075                c(
 8076                    d(
 8077                        |
 8078                    )
 8079                    |
 8080                |)
 8081            );
 8082        "});
 8083
 8084        // handle auto-indent when there are multiple cursors on the same line
 8085        cx.set_state(indoc! {"
 8086            const a: B = (
 8087                c(
 8088            |   |    
 8089            |    )
 8090            );
 8091        "});
 8092        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8093        cx.assert_editor_state(indoc! {"
 8094            const a: B = (
 8095                c(
 8096                    |
 8097                |)
 8098            );
 8099        "});
 8100    }
 8101
 8102    #[gpui::test]
 8103    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 8104        let mut cx = EditorTestContext::new(cx).await;
 8105
 8106        cx.set_state(indoc! {"
 8107              [one} [two}
 8108            three
 8109             four"});
 8110        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8111        cx.assert_editor_state(indoc! {"
 8112                [one} [two}
 8113            three
 8114             four"});
 8115
 8116        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8117        cx.assert_editor_state(indoc! {"
 8118            [one} [two}
 8119            three
 8120             four"});
 8121
 8122        // select across line ending
 8123        cx.set_state(indoc! {"
 8124            one two
 8125            t[hree
 8126            } four"});
 8127        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8128        cx.assert_editor_state(indoc! {"
 8129            one two
 8130                t[hree
 8131            } four"});
 8132
 8133        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8134        cx.assert_editor_state(indoc! {"
 8135            one two
 8136            t[hree
 8137            } four"});
 8138
 8139        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8140        cx.set_state(indoc! {"
 8141            one two
 8142            |three
 8143                four"});
 8144        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8145        cx.assert_editor_state(indoc! {"
 8146            one two
 8147                |three
 8148                four"});
 8149
 8150        cx.set_state(indoc! {"
 8151            one two
 8152            |    three
 8153             four"});
 8154        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8155        cx.assert_editor_state(indoc! {"
 8156            one two
 8157            |three
 8158             four"});
 8159    }
 8160
 8161    #[gpui::test]
 8162    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 8163        let mut cx = EditorTestContext::new(cx).await;
 8164        cx.update(|cx| {
 8165            cx.update_global::<Settings, _, _>(|settings, _| {
 8166                settings.editor_overrides.hard_tabs = Some(true);
 8167            });
 8168        });
 8169
 8170        // select two ranges on one line
 8171        cx.set_state(indoc! {"
 8172            [one} [two}
 8173            three
 8174            four"});
 8175        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8176        cx.assert_editor_state(indoc! {"
 8177            \t[one} [two}
 8178            three
 8179            four"});
 8180        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8181        cx.assert_editor_state(indoc! {"
 8182            \t\t[one} [two}
 8183            three
 8184            four"});
 8185        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8186        cx.assert_editor_state(indoc! {"
 8187            \t[one} [two}
 8188            three
 8189            four"});
 8190        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8191        cx.assert_editor_state(indoc! {"
 8192            [one} [two}
 8193            three
 8194            four"});
 8195
 8196        // select across a line ending
 8197        cx.set_state(indoc! {"
 8198            one two
 8199            t[hree
 8200            }four"});
 8201        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8202        cx.assert_editor_state(indoc! {"
 8203            one two
 8204            \tt[hree
 8205            }four"});
 8206        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8207        cx.assert_editor_state(indoc! {"
 8208            one two
 8209            \t\tt[hree
 8210            }four"});
 8211        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8212        cx.assert_editor_state(indoc! {"
 8213            one two
 8214            \tt[hree
 8215            }four"});
 8216        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8217        cx.assert_editor_state(indoc! {"
 8218            one two
 8219            t[hree
 8220            }four"});
 8221
 8222        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8223        cx.set_state(indoc! {"
 8224            one two
 8225            |three
 8226            four"});
 8227        cx.assert_editor_state(indoc! {"
 8228            one two
 8229            |three
 8230            four"});
 8231        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8232        cx.assert_editor_state(indoc! {"
 8233            one two
 8234            \t|three
 8235            four"});
 8236        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8237        cx.assert_editor_state(indoc! {"
 8238            one two
 8239            |three
 8240            four"});
 8241    }
 8242
 8243    #[gpui::test]
 8244    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 8245        cx.set_global(
 8246            Settings::test(cx)
 8247                .with_language_defaults(
 8248                    "TOML",
 8249                    EditorSettings {
 8250                        tab_size: Some(2.try_into().unwrap()),
 8251                        ..Default::default()
 8252                    },
 8253                )
 8254                .with_language_defaults(
 8255                    "Rust",
 8256                    EditorSettings {
 8257                        tab_size: Some(4.try_into().unwrap()),
 8258                        ..Default::default()
 8259                    },
 8260                ),
 8261        );
 8262        let toml_language = Arc::new(Language::new(
 8263            LanguageConfig {
 8264                name: "TOML".into(),
 8265                ..Default::default()
 8266            },
 8267            None,
 8268        ));
 8269        let rust_language = Arc::new(Language::new(
 8270            LanguageConfig {
 8271                name: "Rust".into(),
 8272                ..Default::default()
 8273            },
 8274            None,
 8275        ));
 8276
 8277        let toml_buffer = cx
 8278            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 8279        let rust_buffer = cx.add_model(|cx| {
 8280            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 8281        });
 8282        let multibuffer = cx.add_model(|cx| {
 8283            let mut multibuffer = MultiBuffer::new(0);
 8284            multibuffer.push_excerpts(
 8285                toml_buffer.clone(),
 8286                [ExcerptRange {
 8287                    context: Point::new(0, 0)..Point::new(2, 0),
 8288                    primary: None,
 8289                }],
 8290                cx,
 8291            );
 8292            multibuffer.push_excerpts(
 8293                rust_buffer.clone(),
 8294                [ExcerptRange {
 8295                    context: Point::new(0, 0)..Point::new(1, 0),
 8296                    primary: None,
 8297                }],
 8298                cx,
 8299            );
 8300            multibuffer
 8301        });
 8302
 8303        cx.add_window(Default::default(), |cx| {
 8304            let mut editor = build_editor(multibuffer, cx);
 8305
 8306            assert_eq!(
 8307                editor.text(cx),
 8308                indoc! {"
 8309                    a = 1
 8310                    b = 2
 8311
 8312                    const c: usize = 3;
 8313                "}
 8314            );
 8315
 8316            select_ranges(
 8317                &mut editor,
 8318                indoc! {"
 8319                    [a] = 1
 8320                    b = 2
 8321
 8322                    [const c:] usize = 3;
 8323                "},
 8324                cx,
 8325            );
 8326
 8327            editor.tab(&Tab, cx);
 8328            assert_text_with_selections(
 8329                &mut editor,
 8330                indoc! {"
 8331                      [a] = 1
 8332                    b = 2
 8333
 8334                        [const c:] usize = 3;
 8335                "},
 8336                cx,
 8337            );
 8338            editor.tab_prev(&TabPrev, cx);
 8339            assert_text_with_selections(
 8340                &mut editor,
 8341                indoc! {"
 8342                    [a] = 1
 8343                    b = 2
 8344
 8345                    [const c:] usize = 3;
 8346                "},
 8347                cx,
 8348            );
 8349
 8350            editor
 8351        });
 8352    }
 8353
 8354    #[gpui::test]
 8355    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 8356        let mut cx = EditorTestContext::new(cx).await;
 8357        // Basic backspace
 8358        cx.set_state(indoc! {"
 8359            on|e two three
 8360            fou[r} five six
 8361            seven {eight nine
 8362            ]ten"});
 8363        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8364        cx.assert_editor_state(indoc! {"
 8365            o|e two three
 8366            fou| five six
 8367            seven |ten"});
 8368
 8369        // Test backspace inside and around indents
 8370        cx.set_state(indoc! {"
 8371            zero
 8372                |one
 8373                    |two
 8374                | | |  three
 8375            |  |  four"});
 8376        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8377        cx.assert_editor_state(indoc! {"
 8378            zero
 8379            |one
 8380                |two
 8381            |  three|  four"});
 8382
 8383        // Test backspace with line_mode set to true
 8384        cx.update_editor(|e, _| e.selections.line_mode = true);
 8385        cx.set_state(indoc! {"
 8386            The |quick |brown
 8387            fox jumps over
 8388            the lazy dog
 8389            |The qu[ick b}rown"});
 8390        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8391        cx.assert_editor_state(indoc! {"
 8392            |fox jumps over
 8393            the lazy dog|"});
 8394    }
 8395
 8396    #[gpui::test]
 8397    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8398        let mut cx = EditorTestContext::new(cx).await;
 8399
 8400        cx.set_state(indoc! {"
 8401            on|e two three
 8402            fou[r} five six
 8403            seven {eight nine
 8404            ]ten"});
 8405        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8406        cx.assert_editor_state(indoc! {"
 8407            on| two three
 8408            fou| five six
 8409            seven |ten"});
 8410
 8411        // Test backspace with line_mode set to true
 8412        cx.update_editor(|e, _| e.selections.line_mode = true);
 8413        cx.set_state(indoc! {"
 8414            The |quick |brown
 8415            fox {jum]ps over
 8416            the lazy dog
 8417            |The qu[ick b}rown"});
 8418        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8419        cx.assert_editor_state("|the lazy dog|");
 8420    }
 8421
 8422    #[gpui::test]
 8423    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8424        cx.set_global(Settings::test(cx));
 8425        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8426        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8427        view.update(cx, |view, cx| {
 8428            view.change_selections(None, cx, |s| {
 8429                s.select_display_ranges([
 8430                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8431                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8432                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8433                ])
 8434            });
 8435            view.delete_line(&DeleteLine, cx);
 8436            assert_eq!(view.display_text(cx), "ghi");
 8437            assert_eq!(
 8438                view.selections.display_ranges(cx),
 8439                vec![
 8440                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8441                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8442                ]
 8443            );
 8444        });
 8445
 8446        cx.set_global(Settings::test(cx));
 8447        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8448        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8449        view.update(cx, |view, cx| {
 8450            view.change_selections(None, cx, |s| {
 8451                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8452            });
 8453            view.delete_line(&DeleteLine, cx);
 8454            assert_eq!(view.display_text(cx), "ghi\n");
 8455            assert_eq!(
 8456                view.selections.display_ranges(cx),
 8457                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8458            );
 8459        });
 8460    }
 8461
 8462    #[gpui::test]
 8463    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8464        cx.set_global(Settings::test(cx));
 8465        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8466        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8467        view.update(cx, |view, cx| {
 8468            view.change_selections(None, cx, |s| {
 8469                s.select_display_ranges([
 8470                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8471                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8472                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8473                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8474                ])
 8475            });
 8476            view.duplicate_line(&DuplicateLine, cx);
 8477            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8478            assert_eq!(
 8479                view.selections.display_ranges(cx),
 8480                vec![
 8481                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8482                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8483                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8484                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8485                ]
 8486            );
 8487        });
 8488
 8489        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8490        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8491        view.update(cx, |view, cx| {
 8492            view.change_selections(None, cx, |s| {
 8493                s.select_display_ranges([
 8494                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8495                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8496                ])
 8497            });
 8498            view.duplicate_line(&DuplicateLine, cx);
 8499            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8500            assert_eq!(
 8501                view.selections.display_ranges(cx),
 8502                vec![
 8503                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8504                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8505                ]
 8506            );
 8507        });
 8508    }
 8509
 8510    #[gpui::test]
 8511    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8512        cx.set_global(Settings::test(cx));
 8513        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8514        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8515        view.update(cx, |view, cx| {
 8516            view.fold_ranges(
 8517                vec![
 8518                    Point::new(0, 2)..Point::new(1, 2),
 8519                    Point::new(2, 3)..Point::new(4, 1),
 8520                    Point::new(7, 0)..Point::new(8, 4),
 8521                ],
 8522                cx,
 8523            );
 8524            view.change_selections(None, cx, |s| {
 8525                s.select_display_ranges([
 8526                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8527                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8528                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8529                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8530                ])
 8531            });
 8532            assert_eq!(
 8533                view.display_text(cx),
 8534                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8535            );
 8536
 8537            view.move_line_up(&MoveLineUp, cx);
 8538            assert_eq!(
 8539                view.display_text(cx),
 8540                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8541            );
 8542            assert_eq!(
 8543                view.selections.display_ranges(cx),
 8544                vec![
 8545                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8546                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8547                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8548                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8549                ]
 8550            );
 8551        });
 8552
 8553        view.update(cx, |view, cx| {
 8554            view.move_line_down(&MoveLineDown, cx);
 8555            assert_eq!(
 8556                view.display_text(cx),
 8557                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8558            );
 8559            assert_eq!(
 8560                view.selections.display_ranges(cx),
 8561                vec![
 8562                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8563                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8564                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8565                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8566                ]
 8567            );
 8568        });
 8569
 8570        view.update(cx, |view, cx| {
 8571            view.move_line_down(&MoveLineDown, cx);
 8572            assert_eq!(
 8573                view.display_text(cx),
 8574                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8575            );
 8576            assert_eq!(
 8577                view.selections.display_ranges(cx),
 8578                vec![
 8579                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8580                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8581                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8582                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8583                ]
 8584            );
 8585        });
 8586
 8587        view.update(cx, |view, cx| {
 8588            view.move_line_up(&MoveLineUp, cx);
 8589            assert_eq!(
 8590                view.display_text(cx),
 8591                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8592            );
 8593            assert_eq!(
 8594                view.selections.display_ranges(cx),
 8595                vec![
 8596                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8597                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8598                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8599                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8600                ]
 8601            );
 8602        });
 8603    }
 8604
 8605    #[gpui::test]
 8606    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8607        cx.set_global(Settings::test(cx));
 8608        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8609        let snapshot = buffer.read(cx).snapshot(cx);
 8610        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8611        editor.update(cx, |editor, cx| {
 8612            editor.insert_blocks(
 8613                [BlockProperties {
 8614                    style: BlockStyle::Fixed,
 8615                    position: snapshot.anchor_after(Point::new(2, 0)),
 8616                    disposition: BlockDisposition::Below,
 8617                    height: 1,
 8618                    render: Arc::new(|_| Empty::new().boxed()),
 8619                }],
 8620                cx,
 8621            );
 8622            editor.change_selections(None, cx, |s| {
 8623                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8624            });
 8625            editor.move_line_down(&MoveLineDown, cx);
 8626        });
 8627    }
 8628
 8629    #[gpui::test]
 8630    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8631        cx.set_global(Settings::test(cx));
 8632
 8633        cx.add_window(Default::default(), |cx| {
 8634            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8635
 8636            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8637            editor.transpose(&Default::default(), cx);
 8638            assert_eq!(editor.text(cx), "bac");
 8639            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8640
 8641            editor.transpose(&Default::default(), cx);
 8642            assert_eq!(editor.text(cx), "bca");
 8643            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8644
 8645            editor.transpose(&Default::default(), cx);
 8646            assert_eq!(editor.text(cx), "bac");
 8647            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8648
 8649            editor
 8650        })
 8651        .1;
 8652
 8653        cx.add_window(Default::default(), |cx| {
 8654            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8655
 8656            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8657            editor.transpose(&Default::default(), cx);
 8658            assert_eq!(editor.text(cx), "acb\nde");
 8659            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8660
 8661            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8662            editor.transpose(&Default::default(), cx);
 8663            assert_eq!(editor.text(cx), "acbd\ne");
 8664            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8665
 8666            editor.transpose(&Default::default(), cx);
 8667            assert_eq!(editor.text(cx), "acbde\n");
 8668            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8669
 8670            editor.transpose(&Default::default(), cx);
 8671            assert_eq!(editor.text(cx), "acbd\ne");
 8672            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8673
 8674            editor
 8675        })
 8676        .1;
 8677
 8678        cx.add_window(Default::default(), |cx| {
 8679            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8680
 8681            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8682            editor.transpose(&Default::default(), cx);
 8683            assert_eq!(editor.text(cx), "bacd\ne");
 8684            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8685
 8686            editor.transpose(&Default::default(), cx);
 8687            assert_eq!(editor.text(cx), "bcade\n");
 8688            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8689
 8690            editor.transpose(&Default::default(), cx);
 8691            assert_eq!(editor.text(cx), "bcda\ne");
 8692            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8693
 8694            editor.transpose(&Default::default(), cx);
 8695            assert_eq!(editor.text(cx), "bcade\n");
 8696            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8697
 8698            editor.transpose(&Default::default(), cx);
 8699            assert_eq!(editor.text(cx), "bcaed\n");
 8700            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8701
 8702            editor
 8703        })
 8704        .1;
 8705
 8706        cx.add_window(Default::default(), |cx| {
 8707            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8708
 8709            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8710            editor.transpose(&Default::default(), cx);
 8711            assert_eq!(editor.text(cx), "🏀🍐✋");
 8712            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8713
 8714            editor.transpose(&Default::default(), cx);
 8715            assert_eq!(editor.text(cx), "🏀✋🍐");
 8716            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8717
 8718            editor.transpose(&Default::default(), cx);
 8719            assert_eq!(editor.text(cx), "🏀🍐✋");
 8720            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8721
 8722            editor
 8723        })
 8724        .1;
 8725    }
 8726
 8727    #[gpui::test]
 8728    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8729        let mut cx = EditorTestContext::new(cx).await;
 8730
 8731        cx.set_state("[one✅ }two [three }four [five }six ");
 8732        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8733        cx.assert_editor_state("|two |four |six ");
 8734
 8735        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8736        cx.set_state("two |four |six |");
 8737        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8738        cx.assert_editor_state("two one✅ |four three |six five |");
 8739
 8740        // Paste again but with only two cursors. Since the number of cursors doesn't
 8741        // match the number of slices in the clipboard, the entire clipboard text
 8742        // is pasted at each cursor.
 8743        cx.set_state("|two one✅ four three six five |");
 8744        cx.update_editor(|e, cx| {
 8745            e.handle_input("( ", cx);
 8746            e.paste(&Paste, cx);
 8747            e.handle_input(") ", cx);
 8748        });
 8749        cx.assert_editor_state(indoc! {"
 8750            ( one✅ 
 8751            three 
 8752            five ) |two one✅ four three six five ( one✅ 
 8753            three 
 8754            five ) |"});
 8755
 8756        // Cut with three selections, one of which is full-line.
 8757        cx.set_state(indoc! {"
 8758            1[2}3
 8759            4|567
 8760            [8}9"});
 8761        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8762        cx.assert_editor_state(indoc! {"
 8763            1|3
 8764            |9"});
 8765
 8766        // Paste with three selections, noticing how the copied selection that was full-line
 8767        // gets inserted before the second cursor.
 8768        cx.set_state(indoc! {"
 8769            1|3
 8770            9|
 8771            [o}ne"});
 8772        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8773        cx.assert_editor_state(indoc! {"
 8774            12|3
 8775            4567
 8776            9|
 8777            8|ne"});
 8778
 8779        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8780        cx.set_state(indoc! {"
 8781            The quick brown
 8782            fox ju|mps over
 8783            the lazy dog"});
 8784        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8785        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8786
 8787        // Paste with three selections, noticing how the copied full-line selection is inserted
 8788        // before the empty selections but replaces the selection that is non-empty.
 8789        cx.set_state(indoc! {"
 8790            T|he quick brown
 8791            [fo}x jumps over
 8792            t|he lazy dog"});
 8793        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8794        cx.assert_editor_state(indoc! {"
 8795            fox jumps over
 8796            T|he quick brown
 8797            fox jumps over
 8798            |x jumps over
 8799            fox jumps over
 8800            t|he lazy dog"});
 8801    }
 8802
 8803    #[gpui::test]
 8804    async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
 8805        let mut cx = EditorTestContext::new(cx).await;
 8806        let language = Arc::new(Language::new(
 8807            LanguageConfig::default(),
 8808            Some(tree_sitter_rust::language()),
 8809        ));
 8810        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8811
 8812        // Cut an indented block, without the leading whitespace.
 8813        cx.set_state(indoc! {"
 8814            const a: B = (
 8815                c(),
 8816                [d(
 8817                    e,
 8818                    f
 8819                )}
 8820            );
 8821        "});
 8822        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8823        cx.assert_editor_state(indoc! {"
 8824            const a: B = (
 8825                c(),
 8826                |
 8827            );
 8828        "});
 8829
 8830        // Paste it at the same position.
 8831        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8832        cx.assert_editor_state(indoc! {"
 8833            const a: B = (
 8834                c(),
 8835                d(
 8836                    e,
 8837                    f
 8838                )|
 8839            );
 8840        "});
 8841
 8842        // Paste it at a line with a lower indent level.
 8843        cx.set_state(indoc! {"
 8844            |
 8845            const a: B = (
 8846                c(),
 8847            );
 8848        "});
 8849        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8850        cx.assert_editor_state(indoc! {"
 8851            d(
 8852                e,
 8853                f
 8854            )|
 8855            const a: B = (
 8856                c(),
 8857            );
 8858        "});
 8859
 8860        // Cut an indented block, with the leading whitespace.
 8861        cx.set_state(indoc! {"
 8862            const a: B = (
 8863                c(),
 8864            [    d(
 8865                    e,
 8866                    f
 8867                )
 8868            });
 8869        "});
 8870        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8871        cx.assert_editor_state(indoc! {"
 8872            const a: B = (
 8873                c(),
 8874            |);
 8875        "});
 8876
 8877        // Paste it at the same position.
 8878        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8879        cx.assert_editor_state(indoc! {"
 8880            const a: B = (
 8881                c(),
 8882                d(
 8883                    e,
 8884                    f
 8885                )
 8886            |);
 8887        "});
 8888
 8889        // Paste it at a line with a higher indent level.
 8890        cx.set_state(indoc! {"
 8891            const a: B = (
 8892                c(),
 8893                d(
 8894                    e,
 8895                    f|
 8896                )
 8897            );
 8898        "});
 8899        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8900        cx.assert_editor_state(indoc! {"
 8901            const a: B = (
 8902                c(),
 8903                d(
 8904                    e,
 8905                    f    d(
 8906                        e,
 8907                        f
 8908                    )
 8909            |
 8910                )
 8911            );
 8912        "});
 8913    }
 8914
 8915    #[gpui::test]
 8916    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8917        cx.set_global(Settings::test(cx));
 8918        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8919        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8920        view.update(cx, |view, cx| {
 8921            view.select_all(&SelectAll, cx);
 8922            assert_eq!(
 8923                view.selections.display_ranges(cx),
 8924                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8925            );
 8926        });
 8927    }
 8928
 8929    #[gpui::test]
 8930    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8931        cx.set_global(Settings::test(cx));
 8932        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8933        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8934        view.update(cx, |view, cx| {
 8935            view.change_selections(None, cx, |s| {
 8936                s.select_display_ranges([
 8937                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8938                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8939                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8940                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8941                ])
 8942            });
 8943            view.select_line(&SelectLine, cx);
 8944            assert_eq!(
 8945                view.selections.display_ranges(cx),
 8946                vec![
 8947                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8948                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8949                ]
 8950            );
 8951        });
 8952
 8953        view.update(cx, |view, cx| {
 8954            view.select_line(&SelectLine, cx);
 8955            assert_eq!(
 8956                view.selections.display_ranges(cx),
 8957                vec![
 8958                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8959                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8960                ]
 8961            );
 8962        });
 8963
 8964        view.update(cx, |view, cx| {
 8965            view.select_line(&SelectLine, cx);
 8966            assert_eq!(
 8967                view.selections.display_ranges(cx),
 8968                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8969            );
 8970        });
 8971    }
 8972
 8973    #[gpui::test]
 8974    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8975        cx.set_global(Settings::test(cx));
 8976        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8977        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8978        view.update(cx, |view, cx| {
 8979            view.fold_ranges(
 8980                vec![
 8981                    Point::new(0, 2)..Point::new(1, 2),
 8982                    Point::new(2, 3)..Point::new(4, 1),
 8983                    Point::new(7, 0)..Point::new(8, 4),
 8984                ],
 8985                cx,
 8986            );
 8987            view.change_selections(None, cx, |s| {
 8988                s.select_display_ranges([
 8989                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8990                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8991                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8992                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8993                ])
 8994            });
 8995            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8996        });
 8997
 8998        view.update(cx, |view, cx| {
 8999            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9000            assert_eq!(
 9001                view.display_text(cx),
 9002                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 9003            );
 9004            assert_eq!(
 9005                view.selections.display_ranges(cx),
 9006                [
 9007                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 9008                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9009                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 9010                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 9011                ]
 9012            );
 9013        });
 9014
 9015        view.update(cx, |view, cx| {
 9016            view.change_selections(None, cx, |s| {
 9017                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 9018            });
 9019            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9020            assert_eq!(
 9021                view.display_text(cx),
 9022                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 9023            );
 9024            assert_eq!(
 9025                view.selections.display_ranges(cx),
 9026                [
 9027                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 9028                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 9029                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9030                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 9031                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 9032                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 9033                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 9034                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 9035                ]
 9036            );
 9037        });
 9038    }
 9039
 9040    #[gpui::test]
 9041    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 9042        cx.set_global(Settings::test(cx));
 9043        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 9044        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9045
 9046        view.update(cx, |view, cx| {
 9047            view.change_selections(None, cx, |s| {
 9048                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 9049            });
 9050        });
 9051        view.update(cx, |view, cx| {
 9052            view.add_selection_above(&AddSelectionAbove, cx);
 9053            assert_eq!(
 9054                view.selections.display_ranges(cx),
 9055                vec![
 9056                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9057                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9058                ]
 9059            );
 9060        });
 9061
 9062        view.update(cx, |view, cx| {
 9063            view.add_selection_above(&AddSelectionAbove, cx);
 9064            assert_eq!(
 9065                view.selections.display_ranges(cx),
 9066                vec![
 9067                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9068                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9069                ]
 9070            );
 9071        });
 9072
 9073        view.update(cx, |view, cx| {
 9074            view.add_selection_below(&AddSelectionBelow, cx);
 9075            assert_eq!(
 9076                view.selections.display_ranges(cx),
 9077                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9078            );
 9079
 9080            view.undo_selection(&UndoSelection, cx);
 9081            assert_eq!(
 9082                view.selections.display_ranges(cx),
 9083                vec![
 9084                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9085                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9086                ]
 9087            );
 9088
 9089            view.redo_selection(&RedoSelection, cx);
 9090            assert_eq!(
 9091                view.selections.display_ranges(cx),
 9092                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9093            );
 9094        });
 9095
 9096        view.update(cx, |view, cx| {
 9097            view.add_selection_below(&AddSelectionBelow, cx);
 9098            assert_eq!(
 9099                view.selections.display_ranges(cx),
 9100                vec![
 9101                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9102                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9103                ]
 9104            );
 9105        });
 9106
 9107        view.update(cx, |view, cx| {
 9108            view.add_selection_below(&AddSelectionBelow, cx);
 9109            assert_eq!(
 9110                view.selections.display_ranges(cx),
 9111                vec![
 9112                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9113                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9114                ]
 9115            );
 9116        });
 9117
 9118        view.update(cx, |view, cx| {
 9119            view.change_selections(None, cx, |s| {
 9120                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 9121            });
 9122        });
 9123        view.update(cx, |view, cx| {
 9124            view.add_selection_below(&AddSelectionBelow, cx);
 9125            assert_eq!(
 9126                view.selections.display_ranges(cx),
 9127                vec![
 9128                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9129                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9130                ]
 9131            );
 9132        });
 9133
 9134        view.update(cx, |view, cx| {
 9135            view.add_selection_below(&AddSelectionBelow, cx);
 9136            assert_eq!(
 9137                view.selections.display_ranges(cx),
 9138                vec![
 9139                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9140                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9141                ]
 9142            );
 9143        });
 9144
 9145        view.update(cx, |view, cx| {
 9146            view.add_selection_above(&AddSelectionAbove, cx);
 9147            assert_eq!(
 9148                view.selections.display_ranges(cx),
 9149                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9150            );
 9151        });
 9152
 9153        view.update(cx, |view, cx| {
 9154            view.add_selection_above(&AddSelectionAbove, cx);
 9155            assert_eq!(
 9156                view.selections.display_ranges(cx),
 9157                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9158            );
 9159        });
 9160
 9161        view.update(cx, |view, cx| {
 9162            view.change_selections(None, cx, |s| {
 9163                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 9164            });
 9165            view.add_selection_below(&AddSelectionBelow, cx);
 9166            assert_eq!(
 9167                view.selections.display_ranges(cx),
 9168                vec![
 9169                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9170                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9171                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9172                ]
 9173            );
 9174        });
 9175
 9176        view.update(cx, |view, cx| {
 9177            view.add_selection_below(&AddSelectionBelow, cx);
 9178            assert_eq!(
 9179                view.selections.display_ranges(cx),
 9180                vec![
 9181                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9182                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9183                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9184                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 9185                ]
 9186            );
 9187        });
 9188
 9189        view.update(cx, |view, cx| {
 9190            view.add_selection_above(&AddSelectionAbove, cx);
 9191            assert_eq!(
 9192                view.selections.display_ranges(cx),
 9193                vec![
 9194                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9195                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9196                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9197                ]
 9198            );
 9199        });
 9200
 9201        view.update(cx, |view, cx| {
 9202            view.change_selections(None, cx, |s| {
 9203                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 9204            });
 9205        });
 9206        view.update(cx, |view, cx| {
 9207            view.add_selection_above(&AddSelectionAbove, cx);
 9208            assert_eq!(
 9209                view.selections.display_ranges(cx),
 9210                vec![
 9211                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 9212                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9213                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9214                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9215                ]
 9216            );
 9217        });
 9218
 9219        view.update(cx, |view, cx| {
 9220            view.add_selection_below(&AddSelectionBelow, cx);
 9221            assert_eq!(
 9222                view.selections.display_ranges(cx),
 9223                vec![
 9224                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9225                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9226                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9227                ]
 9228            );
 9229        });
 9230    }
 9231
 9232    #[gpui::test]
 9233    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 9234        cx.set_global(Settings::test(cx));
 9235
 9236        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 9237        let buffer = MultiBuffer::build_simple(&text, cx);
 9238        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9239
 9240        view.update(cx, |view, cx| {
 9241            view.change_selections(None, cx, |s| {
 9242                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 9243            });
 9244            view.select_next(
 9245                &SelectNext {
 9246                    replace_newest: false,
 9247                },
 9248                cx,
 9249            );
 9250            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 9251
 9252            view.select_next(
 9253                &SelectNext {
 9254                    replace_newest: false,
 9255                },
 9256                cx,
 9257            );
 9258            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 9259
 9260            view.undo_selection(&UndoSelection, cx);
 9261            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 9262
 9263            view.redo_selection(&RedoSelection, cx);
 9264            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 9265
 9266            view.select_next(
 9267                &SelectNext {
 9268                    replace_newest: false,
 9269                },
 9270                cx,
 9271            );
 9272            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 9273
 9274            view.select_next(
 9275                &SelectNext {
 9276                    replace_newest: false,
 9277                },
 9278                cx,
 9279            );
 9280            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 9281        });
 9282    }
 9283
 9284    #[gpui::test]
 9285    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 9286        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9287        let language = Arc::new(Language::new(
 9288            LanguageConfig::default(),
 9289            Some(tree_sitter_rust::language()),
 9290        ));
 9291
 9292        let text = r#"
 9293            use mod1::mod2::{mod3, mod4};
 9294
 9295            fn fn_1(param1: bool, param2: &str) {
 9296                let var1 = "text";
 9297            }
 9298        "#
 9299        .unindent();
 9300
 9301        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9302        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9303        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9304        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9305            .await;
 9306
 9307        view.update(cx, |view, cx| {
 9308            view.change_selections(None, cx, |s| {
 9309                s.select_display_ranges([
 9310                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9311                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9312                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9313                ]);
 9314            });
 9315            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9316        });
 9317        assert_eq!(
 9318            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 9319            &[
 9320                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9321                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9322                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9323            ]
 9324        );
 9325
 9326        view.update(cx, |view, cx| {
 9327            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9328        });
 9329        assert_eq!(
 9330            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9331            &[
 9332                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9333                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9334            ]
 9335        );
 9336
 9337        view.update(cx, |view, cx| {
 9338            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9339        });
 9340        assert_eq!(
 9341            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9342            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9343        );
 9344
 9345        // Trying to expand the selected syntax node one more time has no effect.
 9346        view.update(cx, |view, cx| {
 9347            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9348        });
 9349        assert_eq!(
 9350            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9351            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9352        );
 9353
 9354        view.update(cx, |view, cx| {
 9355            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9356        });
 9357        assert_eq!(
 9358            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9359            &[
 9360                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9361                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9362            ]
 9363        );
 9364
 9365        view.update(cx, |view, cx| {
 9366            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9367        });
 9368        assert_eq!(
 9369            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9370            &[
 9371                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9372                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9373                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9374            ]
 9375        );
 9376
 9377        view.update(cx, |view, cx| {
 9378            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9379        });
 9380        assert_eq!(
 9381            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9382            &[
 9383                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9384                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9385                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9386            ]
 9387        );
 9388
 9389        // Trying to shrink the selected syntax node one more time has no effect.
 9390        view.update(cx, |view, cx| {
 9391            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9392        });
 9393        assert_eq!(
 9394            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9395            &[
 9396                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9397                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9398                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9399            ]
 9400        );
 9401
 9402        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9403        // a fold.
 9404        view.update(cx, |view, cx| {
 9405            view.fold_ranges(
 9406                vec![
 9407                    Point::new(0, 21)..Point::new(0, 24),
 9408                    Point::new(3, 20)..Point::new(3, 22),
 9409                ],
 9410                cx,
 9411            );
 9412            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9413        });
 9414        assert_eq!(
 9415            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9416            &[
 9417                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9418                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9419                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9420            ]
 9421        );
 9422    }
 9423
 9424    #[gpui::test]
 9425    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9426        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9427        let language = Arc::new(
 9428            Language::new(
 9429                LanguageConfig {
 9430                    brackets: vec![
 9431                        BracketPair {
 9432                            start: "{".to_string(),
 9433                            end: "}".to_string(),
 9434                            close: false,
 9435                            newline: true,
 9436                        },
 9437                        BracketPair {
 9438                            start: "(".to_string(),
 9439                            end: ")".to_string(),
 9440                            close: false,
 9441                            newline: true,
 9442                        },
 9443                    ],
 9444                    ..Default::default()
 9445                },
 9446                Some(tree_sitter_rust::language()),
 9447            )
 9448            .with_indents_query(
 9449                r#"
 9450                (_ "(" ")" @end) @indent
 9451                (_ "{" "}" @end) @indent
 9452                "#,
 9453            )
 9454            .unwrap(),
 9455        );
 9456
 9457        let text = "fn a() {}";
 9458
 9459        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9460        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9461        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9462        editor
 9463            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9464            .await;
 9465
 9466        editor.update(cx, |editor, cx| {
 9467            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 9468            editor.newline(&Newline, cx);
 9469            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9470            assert_eq!(
 9471                editor.selections.ranges(cx),
 9472                &[
 9473                    Point::new(1, 4)..Point::new(1, 4),
 9474                    Point::new(3, 4)..Point::new(3, 4),
 9475                    Point::new(5, 0)..Point::new(5, 0)
 9476                ]
 9477            );
 9478        });
 9479    }
 9480
 9481    #[gpui::test]
 9482    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9483        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9484        let language = Arc::new(Language::new(
 9485            LanguageConfig {
 9486                brackets: vec![
 9487                    BracketPair {
 9488                        start: "{".to_string(),
 9489                        end: "}".to_string(),
 9490                        close: true,
 9491                        newline: true,
 9492                    },
 9493                    BracketPair {
 9494                        start: "/*".to_string(),
 9495                        end: " */".to_string(),
 9496                        close: true,
 9497                        newline: true,
 9498                    },
 9499                    BracketPair {
 9500                        start: "[".to_string(),
 9501                        end: "]".to_string(),
 9502                        close: false,
 9503                        newline: true,
 9504                    },
 9505                ],
 9506                autoclose_before: "})]".to_string(),
 9507                ..Default::default()
 9508            },
 9509            Some(tree_sitter_rust::language()),
 9510        ));
 9511
 9512        let text = r#"
 9513            a
 9514
 9515            /
 9516
 9517        "#
 9518        .unindent();
 9519
 9520        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9521        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9522        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9523        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9524            .await;
 9525
 9526        view.update(cx, |view, cx| {
 9527            view.change_selections(None, cx, |s| {
 9528                s.select_display_ranges([
 9529                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9530                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9531                ])
 9532            });
 9533
 9534            view.handle_input("{", cx);
 9535            view.handle_input("{", cx);
 9536            view.handle_input("{", cx);
 9537            assert_eq!(
 9538                view.text(cx),
 9539                "
 9540                {{{}}}
 9541                {{{}}}
 9542                /
 9543
 9544                "
 9545                .unindent()
 9546            );
 9547
 9548            view.move_right(&MoveRight, cx);
 9549            view.handle_input("}", cx);
 9550            view.handle_input("}", cx);
 9551            view.handle_input("}", cx);
 9552            assert_eq!(
 9553                view.text(cx),
 9554                "
 9555                {{{}}}}
 9556                {{{}}}}
 9557                /
 9558
 9559                "
 9560                .unindent()
 9561            );
 9562
 9563            view.undo(&Undo, cx);
 9564            view.handle_input("/", cx);
 9565            view.handle_input("*", cx);
 9566            assert_eq!(
 9567                view.text(cx),
 9568                "
 9569                /* */
 9570                /* */
 9571                /
 9572
 9573                "
 9574                .unindent()
 9575            );
 9576
 9577            view.undo(&Undo, cx);
 9578            view.change_selections(None, cx, |s| {
 9579                s.select_display_ranges([
 9580                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9581                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9582                ])
 9583            });
 9584            view.handle_input("*", cx);
 9585            assert_eq!(
 9586                view.text(cx),
 9587                "
 9588                a
 9589
 9590                /*
 9591                *
 9592                "
 9593                .unindent()
 9594            );
 9595
 9596            // Don't autoclose if the next character isn't whitespace and isn't
 9597            // listed in the language's "autoclose_before" section.
 9598            view.finalize_last_transaction(cx);
 9599            view.change_selections(None, cx, |s| {
 9600                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 9601            });
 9602            view.handle_input("{", cx);
 9603            assert_eq!(
 9604                view.text(cx),
 9605                "
 9606                {a
 9607
 9608                /*
 9609                *
 9610                "
 9611                .unindent()
 9612            );
 9613
 9614            view.undo(&Undo, cx);
 9615            view.change_selections(None, cx, |s| {
 9616                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 9617            });
 9618            view.handle_input("{", cx);
 9619            assert_eq!(
 9620                view.text(cx),
 9621                "
 9622                {a}
 9623
 9624                /*
 9625                *
 9626                "
 9627                .unindent()
 9628            );
 9629            assert_eq!(
 9630                view.selections.display_ranges(cx),
 9631                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9632            );
 9633
 9634            view.undo(&Undo, cx);
 9635            view.handle_input("[", cx);
 9636            assert_eq!(
 9637                view.text(cx),
 9638                "
 9639                [a]
 9640                
 9641                /*
 9642                *
 9643                "
 9644                .unindent()
 9645            );
 9646            assert_eq!(
 9647                view.selections.display_ranges(cx),
 9648                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9649            );
 9650
 9651            view.undo(&Undo, cx);
 9652            view.change_selections(None, cx, |s| {
 9653                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9654            });
 9655            view.handle_input("[", cx);
 9656            assert_eq!(
 9657                view.text(cx),
 9658                "
 9659                a[
 9660                
 9661                /*
 9662                *
 9663                "
 9664                .unindent()
 9665            );
 9666            assert_eq!(
 9667                view.selections.display_ranges(cx),
 9668                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9669            );
 9670        });
 9671    }
 9672
 9673    #[gpui::test]
 9674    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9675        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9676        let language = Arc::new(Language::new(
 9677            LanguageConfig {
 9678                brackets: vec![BracketPair {
 9679                    start: "{".to_string(),
 9680                    end: "}".to_string(),
 9681                    close: true,
 9682                    newline: true,
 9683                }],
 9684                ..Default::default()
 9685            },
 9686            Some(tree_sitter_rust::language()),
 9687        ));
 9688
 9689        let text = r#"
 9690            a
 9691            b
 9692            c
 9693        "#
 9694        .unindent();
 9695
 9696        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9697        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9698        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9699        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9700            .await;
 9701
 9702        view.update(cx, |view, cx| {
 9703            view.change_selections(None, cx, |s| {
 9704                s.select_display_ranges([
 9705                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9706                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9707                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9708                ])
 9709            });
 9710
 9711            view.handle_input("{", cx);
 9712            view.handle_input("{", cx);
 9713            view.handle_input("{", cx);
 9714            assert_eq!(
 9715                view.text(cx),
 9716                "
 9717                {{{a}}}
 9718                {{{b}}}
 9719                {{{c}}}
 9720                "
 9721                .unindent()
 9722            );
 9723            assert_eq!(
 9724                view.selections.display_ranges(cx),
 9725                [
 9726                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9727                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9728                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9729                ]
 9730            );
 9731
 9732            view.undo(&Undo, cx);
 9733            assert_eq!(
 9734                view.text(cx),
 9735                "
 9736                a
 9737                b
 9738                c
 9739                "
 9740                .unindent()
 9741            );
 9742            assert_eq!(
 9743                view.selections.display_ranges(cx),
 9744                [
 9745                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9746                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9747                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9748                ]
 9749            );
 9750        });
 9751    }
 9752
 9753    #[gpui::test]
 9754    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9755        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9756        let language = Arc::new(Language::new(
 9757            LanguageConfig {
 9758                brackets: vec![BracketPair {
 9759                    start: "{".to_string(),
 9760                    end: "}".to_string(),
 9761                    close: true,
 9762                    newline: true,
 9763                }],
 9764                autoclose_before: "}".to_string(),
 9765                ..Default::default()
 9766            },
 9767            Some(tree_sitter_rust::language()),
 9768        ));
 9769
 9770        let text = r#"
 9771            a
 9772            b
 9773            c
 9774        "#
 9775        .unindent();
 9776
 9777        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9778        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9779        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9780        editor
 9781            .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9782            .await;
 9783
 9784        editor.update(cx, |editor, cx| {
 9785            editor.change_selections(None, cx, |s| {
 9786                s.select_ranges([
 9787                    Point::new(0, 1)..Point::new(0, 1),
 9788                    Point::new(1, 1)..Point::new(1, 1),
 9789                    Point::new(2, 1)..Point::new(2, 1),
 9790                ])
 9791            });
 9792
 9793            editor.handle_input("{", cx);
 9794            editor.handle_input("{", cx);
 9795            editor.handle_input("_", cx);
 9796            assert_eq!(
 9797                editor.text(cx),
 9798                "
 9799                a{{_}}
 9800                b{{_}}
 9801                c{{_}}
 9802                "
 9803                .unindent()
 9804            );
 9805            assert_eq!(
 9806                editor.selections.ranges::<Point>(cx),
 9807                [
 9808                    Point::new(0, 4)..Point::new(0, 4),
 9809                    Point::new(1, 4)..Point::new(1, 4),
 9810                    Point::new(2, 4)..Point::new(2, 4)
 9811                ]
 9812            );
 9813
 9814            editor.backspace(&Default::default(), cx);
 9815            editor.backspace(&Default::default(), cx);
 9816            assert_eq!(
 9817                editor.text(cx),
 9818                "
 9819                a{}
 9820                b{}
 9821                c{}
 9822                "
 9823                .unindent()
 9824            );
 9825            assert_eq!(
 9826                editor.selections.ranges::<Point>(cx),
 9827                [
 9828                    Point::new(0, 2)..Point::new(0, 2),
 9829                    Point::new(1, 2)..Point::new(1, 2),
 9830                    Point::new(2, 2)..Point::new(2, 2)
 9831                ]
 9832            );
 9833
 9834            editor.delete_to_previous_word_start(&Default::default(), cx);
 9835            assert_eq!(
 9836                editor.text(cx),
 9837                "
 9838                a
 9839                b
 9840                c
 9841                "
 9842                .unindent()
 9843            );
 9844            assert_eq!(
 9845                editor.selections.ranges::<Point>(cx),
 9846                [
 9847                    Point::new(0, 1)..Point::new(0, 1),
 9848                    Point::new(1, 1)..Point::new(1, 1),
 9849                    Point::new(2, 1)..Point::new(2, 1)
 9850                ]
 9851            );
 9852        });
 9853    }
 9854
 9855    #[gpui::test]
 9856    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9857        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9858
 9859        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 9860            a.| b
 9861            a.| b
 9862            a.| b"});
 9863        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9864        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9865
 9866        editor.update(cx, |editor, cx| {
 9867            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9868
 9869            editor
 9870                .insert_snippet(&insertion_ranges, snippet, cx)
 9871                .unwrap();
 9872
 9873            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 9874                let range_markers = ('<', '>');
 9875                let (expected_text, mut selection_ranges_lookup) =
 9876                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 9877                let selection_ranges = selection_ranges_lookup
 9878                    .remove(&range_markers.into())
 9879                    .unwrap();
 9880                assert_eq!(editor.text(cx), expected_text);
 9881                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9882            }
 9883            assert(
 9884                editor,
 9885                cx,
 9886                indoc! {"
 9887                    a.f(<one>, two, <three>) b
 9888                    a.f(<one>, two, <three>) b
 9889                    a.f(<one>, two, <three>) b"},
 9890            );
 9891
 9892            // Can't move earlier than the first tab stop
 9893            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9894            assert(
 9895                editor,
 9896                cx,
 9897                indoc! {"
 9898                    a.f(<one>, two, <three>) b
 9899                    a.f(<one>, two, <three>) b
 9900                    a.f(<one>, two, <three>) b"},
 9901            );
 9902
 9903            assert!(editor.move_to_next_snippet_tabstop(cx));
 9904            assert(
 9905                editor,
 9906                cx,
 9907                indoc! {"
 9908                    a.f(one, <two>, three) b
 9909                    a.f(one, <two>, three) b
 9910                    a.f(one, <two>, three) b"},
 9911            );
 9912
 9913            editor.move_to_prev_snippet_tabstop(cx);
 9914            assert(
 9915                editor,
 9916                cx,
 9917                indoc! {"
 9918                    a.f(<one>, two, <three>) b
 9919                    a.f(<one>, two, <three>) b
 9920                    a.f(<one>, two, <three>) b"},
 9921            );
 9922
 9923            assert!(editor.move_to_next_snippet_tabstop(cx));
 9924            assert(
 9925                editor,
 9926                cx,
 9927                indoc! {"
 9928                    a.f(one, <two>, three) b
 9929                    a.f(one, <two>, three) b
 9930                    a.f(one, <two>, three) b"},
 9931            );
 9932            assert!(editor.move_to_next_snippet_tabstop(cx));
 9933            assert(
 9934                editor,
 9935                cx,
 9936                indoc! {"
 9937                    a.f(one, two, three)<> b
 9938                    a.f(one, two, three)<> b
 9939                    a.f(one, two, three)<> b"},
 9940            );
 9941
 9942            // As soon as the last tab stop is reached, snippet state is gone
 9943            editor.move_to_prev_snippet_tabstop(cx);
 9944            assert(
 9945                editor,
 9946                cx,
 9947                indoc! {"
 9948                    a.f(one, two, three)<> b
 9949                    a.f(one, two, three)<> b
 9950                    a.f(one, two, three)<> b"},
 9951            );
 9952        });
 9953    }
 9954
 9955    #[gpui::test]
 9956    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9957        cx.foreground().forbid_parking();
 9958
 9959        let mut language = Language::new(
 9960            LanguageConfig {
 9961                name: "Rust".into(),
 9962                path_suffixes: vec!["rs".to_string()],
 9963                ..Default::default()
 9964            },
 9965            Some(tree_sitter_rust::language()),
 9966        );
 9967        let mut fake_servers = language
 9968            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9969                capabilities: lsp::ServerCapabilities {
 9970                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9971                    ..Default::default()
 9972                },
 9973                ..Default::default()
 9974            }))
 9975            .await;
 9976
 9977        let fs = FakeFs::new(cx.background().clone());
 9978        fs.insert_file("/file.rs", Default::default()).await;
 9979
 9980        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9981        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9982        let buffer = project
 9983            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9984            .await
 9985            .unwrap();
 9986
 9987        cx.foreground().start_waiting();
 9988        let fake_server = fake_servers.next().await.unwrap();
 9989
 9990        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9991        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9992        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9993        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9994
 9995        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9996        fake_server
 9997            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9998                assert_eq!(
 9999                    params.text_document.uri,
10000                    lsp::Url::from_file_path("/file.rs").unwrap()
10001                );
10002                assert_eq!(params.options.tab_size, 4);
10003                Ok(Some(vec![lsp::TextEdit::new(
10004                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10005                    ", ".to_string(),
10006                )]))
10007            })
10008            .next()
10009            .await;
10010        cx.foreground().start_waiting();
10011        save.await.unwrap();
10012        assert_eq!(
10013            editor.read_with(cx, |editor, cx| editor.text(cx)),
10014            "one, two\nthree\n"
10015        );
10016        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10017
10018        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10019        assert!(cx.read(|cx| editor.is_dirty(cx)));
10020
10021        // Ensure we can still save even if formatting hangs.
10022        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10023            assert_eq!(
10024                params.text_document.uri,
10025                lsp::Url::from_file_path("/file.rs").unwrap()
10026            );
10027            futures::future::pending::<()>().await;
10028            unreachable!()
10029        });
10030        let save = cx.update(|cx| editor.save(project.clone(), cx));
10031        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10032        cx.foreground().start_waiting();
10033        save.await.unwrap();
10034        assert_eq!(
10035            editor.read_with(cx, |editor, cx| editor.text(cx)),
10036            "one\ntwo\nthree\n"
10037        );
10038        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10039
10040        // Set rust language override and assert overriden tabsize is sent to language server
10041        cx.update(|cx| {
10042            cx.update_global::<Settings, _, _>(|settings, _| {
10043                settings.language_overrides.insert(
10044                    "Rust".into(),
10045                    EditorSettings {
10046                        tab_size: Some(8.try_into().unwrap()),
10047                        ..Default::default()
10048                    },
10049                );
10050            })
10051        });
10052
10053        let save = cx.update(|cx| editor.save(project.clone(), cx));
10054        fake_server
10055            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10056                assert_eq!(
10057                    params.text_document.uri,
10058                    lsp::Url::from_file_path("/file.rs").unwrap()
10059                );
10060                assert_eq!(params.options.tab_size, 8);
10061                Ok(Some(vec![]))
10062            })
10063            .next()
10064            .await;
10065        cx.foreground().start_waiting();
10066        save.await.unwrap();
10067    }
10068
10069    #[gpui::test]
10070    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
10071        cx.foreground().forbid_parking();
10072
10073        let mut language = Language::new(
10074            LanguageConfig {
10075                name: "Rust".into(),
10076                path_suffixes: vec!["rs".to_string()],
10077                ..Default::default()
10078            },
10079            Some(tree_sitter_rust::language()),
10080        );
10081        let mut fake_servers = language
10082            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10083                capabilities: lsp::ServerCapabilities {
10084                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
10085                    ..Default::default()
10086                },
10087                ..Default::default()
10088            }))
10089            .await;
10090
10091        let fs = FakeFs::new(cx.background().clone());
10092        fs.insert_file("/file.rs", Default::default()).await;
10093
10094        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10095        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10096        let buffer = project
10097            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10098            .await
10099            .unwrap();
10100
10101        cx.foreground().start_waiting();
10102        let fake_server = fake_servers.next().await.unwrap();
10103
10104        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10105        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10106        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10107        assert!(cx.read(|cx| editor.is_dirty(cx)));
10108
10109        let save = cx.update(|cx| editor.save(project.clone(), cx));
10110        fake_server
10111            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10112                assert_eq!(
10113                    params.text_document.uri,
10114                    lsp::Url::from_file_path("/file.rs").unwrap()
10115                );
10116                assert_eq!(params.options.tab_size, 4);
10117                Ok(Some(vec![lsp::TextEdit::new(
10118                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10119                    ", ".to_string(),
10120                )]))
10121            })
10122            .next()
10123            .await;
10124        cx.foreground().start_waiting();
10125        save.await.unwrap();
10126        assert_eq!(
10127            editor.read_with(cx, |editor, cx| editor.text(cx)),
10128            "one, two\nthree\n"
10129        );
10130        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10131
10132        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10133        assert!(cx.read(|cx| editor.is_dirty(cx)));
10134
10135        // Ensure we can still save even if formatting hangs.
10136        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
10137            move |params, _| async move {
10138                assert_eq!(
10139                    params.text_document.uri,
10140                    lsp::Url::from_file_path("/file.rs").unwrap()
10141                );
10142                futures::future::pending::<()>().await;
10143                unreachable!()
10144            },
10145        );
10146        let save = cx.update(|cx| editor.save(project.clone(), cx));
10147        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10148        cx.foreground().start_waiting();
10149        save.await.unwrap();
10150        assert_eq!(
10151            editor.read_with(cx, |editor, cx| editor.text(cx)),
10152            "one\ntwo\nthree\n"
10153        );
10154        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10155
10156        // Set rust language override and assert overriden tabsize is sent to language server
10157        cx.update(|cx| {
10158            cx.update_global::<Settings, _, _>(|settings, _| {
10159                settings.language_overrides.insert(
10160                    "Rust".into(),
10161                    EditorSettings {
10162                        tab_size: Some(8.try_into().unwrap()),
10163                        ..Default::default()
10164                    },
10165                );
10166            })
10167        });
10168
10169        let save = cx.update(|cx| editor.save(project.clone(), cx));
10170        fake_server
10171            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10172                assert_eq!(
10173                    params.text_document.uri,
10174                    lsp::Url::from_file_path("/file.rs").unwrap()
10175                );
10176                assert_eq!(params.options.tab_size, 8);
10177                Ok(Some(vec![]))
10178            })
10179            .next()
10180            .await;
10181        cx.foreground().start_waiting();
10182        save.await.unwrap();
10183    }
10184
10185    #[gpui::test]
10186    async fn test_completion(cx: &mut gpui::TestAppContext) {
10187        let mut cx = EditorLspTestContext::new_rust(
10188            lsp::ServerCapabilities {
10189                completion_provider: Some(lsp::CompletionOptions {
10190                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
10191                    ..Default::default()
10192                }),
10193                ..Default::default()
10194            },
10195            cx,
10196        )
10197        .await;
10198
10199        cx.set_state(indoc! {"
10200            one|
10201            two
10202            three"});
10203        cx.simulate_keystroke(".");
10204        handle_completion_request(
10205            &mut cx,
10206            indoc! {"
10207                one.|<>
10208                two
10209                three"},
10210            vec!["first_completion", "second_completion"],
10211        )
10212        .await;
10213        cx.condition(|editor, _| editor.context_menu_visible())
10214            .await;
10215        let apply_additional_edits = cx.update_editor(|editor, cx| {
10216            editor.move_down(&MoveDown, cx);
10217            editor
10218                .confirm_completion(&ConfirmCompletion::default(), cx)
10219                .unwrap()
10220        });
10221        cx.assert_editor_state(indoc! {"
10222            one.second_completion|
10223            two
10224            three"});
10225
10226        handle_resolve_completion_request(
10227            &mut cx,
10228            Some((
10229                indoc! {"
10230                    one.second_completion
10231                    two
10232                    three<>"},
10233                "\nadditional edit",
10234            )),
10235        )
10236        .await;
10237        apply_additional_edits.await.unwrap();
10238        cx.assert_editor_state(indoc! {"
10239            one.second_completion|
10240            two
10241            three
10242            additional edit"});
10243
10244        cx.set_state(indoc! {"
10245            one.second_completion
10246            two|
10247            three|
10248            additional edit"});
10249        cx.simulate_keystroke(" ");
10250        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10251        cx.simulate_keystroke("s");
10252        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10253
10254        cx.assert_editor_state(indoc! {"
10255            one.second_completion
10256            two s|
10257            three s|
10258            additional edit"});
10259        handle_completion_request(
10260            &mut cx,
10261            indoc! {"
10262                one.second_completion
10263                two s
10264                three <s|>
10265                additional edit"},
10266            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10267        )
10268        .await;
10269        cx.condition(|editor, _| editor.context_menu_visible())
10270            .await;
10271
10272        cx.simulate_keystroke("i");
10273
10274        handle_completion_request(
10275            &mut cx,
10276            indoc! {"
10277                one.second_completion
10278                two si
10279                three <si|>
10280                additional edit"},
10281            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10282        )
10283        .await;
10284        cx.condition(|editor, _| editor.context_menu_visible())
10285            .await;
10286
10287        let apply_additional_edits = cx.update_editor(|editor, cx| {
10288            editor
10289                .confirm_completion(&ConfirmCompletion::default(), cx)
10290                .unwrap()
10291        });
10292        cx.assert_editor_state(indoc! {"
10293            one.second_completion
10294            two sixth_completion|
10295            three sixth_completion|
10296            additional edit"});
10297
10298        handle_resolve_completion_request(&mut cx, None).await;
10299        apply_additional_edits.await.unwrap();
10300
10301        cx.update(|cx| {
10302            cx.update_global::<Settings, _, _>(|settings, _| {
10303                settings.show_completions_on_input = false;
10304            })
10305        });
10306        cx.set_state("editor|");
10307        cx.simulate_keystroke(".");
10308        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10309        cx.simulate_keystroke("c");
10310        cx.simulate_keystroke("l");
10311        cx.simulate_keystroke("o");
10312        cx.assert_editor_state("editor.clo|");
10313        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10314        cx.update_editor(|editor, cx| {
10315            editor.show_completions(&ShowCompletions, cx);
10316        });
10317        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
10318        cx.condition(|editor, _| editor.context_menu_visible())
10319            .await;
10320        let apply_additional_edits = cx.update_editor(|editor, cx| {
10321            editor
10322                .confirm_completion(&ConfirmCompletion::default(), cx)
10323                .unwrap()
10324        });
10325        cx.assert_editor_state("editor.close|");
10326        handle_resolve_completion_request(&mut cx, None).await;
10327        apply_additional_edits.await.unwrap();
10328
10329        // Handle completion request passing a marked string specifying where the completion
10330        // should be triggered from using '|' character, what range should be replaced, and what completions
10331        // should be returned using '<' and '>' to delimit the range
10332        async fn handle_completion_request<'a>(
10333            cx: &mut EditorLspTestContext<'a>,
10334            marked_string: &str,
10335            completions: Vec<&'static str>,
10336        ) {
10337            let complete_from_marker: TextRangeMarker = '|'.into();
10338            let replace_range_marker: TextRangeMarker = ('<', '>').into();
10339            let (_, mut marked_ranges) = marked_text_ranges_by(
10340                marked_string,
10341                vec![complete_from_marker.clone(), replace_range_marker.clone()],
10342            );
10343
10344            let complete_from_position =
10345                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
10346            let replace_range =
10347                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10348
10349            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
10350                let completions = completions.clone();
10351                async move {
10352                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
10353                    assert_eq!(
10354                        params.text_document_position.position,
10355                        complete_from_position
10356                    );
10357                    Ok(Some(lsp::CompletionResponse::Array(
10358                        completions
10359                            .iter()
10360                            .map(|completion_text| lsp::CompletionItem {
10361                                label: completion_text.to_string(),
10362                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
10363                                    range: replace_range.clone(),
10364                                    new_text: completion_text.to_string(),
10365                                })),
10366                                ..Default::default()
10367                            })
10368                            .collect(),
10369                    )))
10370                }
10371            })
10372            .next()
10373            .await;
10374        }
10375
10376        async fn handle_resolve_completion_request<'a>(
10377            cx: &mut EditorLspTestContext<'a>,
10378            edit: Option<(&'static str, &'static str)>,
10379        ) {
10380            let edit = edit.map(|(marked_string, new_text)| {
10381                let replace_range_marker: TextRangeMarker = ('<', '>').into();
10382                let (_, mut marked_ranges) =
10383                    marked_text_ranges_by(marked_string, vec![replace_range_marker.clone()]);
10384
10385                let replace_range = cx
10386                    .to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10387
10388                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
10389            });
10390
10391            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
10392                let edit = edit.clone();
10393                async move {
10394                    Ok(lsp::CompletionItem {
10395                        additional_text_edits: edit,
10396                        ..Default::default()
10397                    })
10398                }
10399            })
10400            .next()
10401            .await;
10402        }
10403    }
10404
10405    #[gpui::test]
10406    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
10407        cx.update(|cx| cx.set_global(Settings::test(cx)));
10408        let language = Arc::new(Language::new(
10409            LanguageConfig {
10410                line_comment: Some("// ".to_string()),
10411                ..Default::default()
10412            },
10413            Some(tree_sitter_rust::language()),
10414        ));
10415
10416        let text = "
10417            fn a() {
10418                //b();
10419                // c();
10420                //  d();
10421            }
10422        "
10423        .unindent();
10424
10425        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10426        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10427        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10428
10429        view.update(cx, |editor, cx| {
10430            // If multiple selections intersect a line, the line is only
10431            // toggled once.
10432            editor.change_selections(None, cx, |s| {
10433                s.select_display_ranges([
10434                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
10435                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
10436                ])
10437            });
10438            editor.toggle_comments(&ToggleComments, cx);
10439            assert_eq!(
10440                editor.text(cx),
10441                "
10442                    fn a() {
10443                        b();
10444                        c();
10445                         d();
10446                    }
10447                "
10448                .unindent()
10449            );
10450
10451            // The comment prefix is inserted at the same column for every line
10452            // in a selection.
10453            editor.change_selections(None, cx, |s| {
10454                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
10455            });
10456            editor.toggle_comments(&ToggleComments, cx);
10457            assert_eq!(
10458                editor.text(cx),
10459                "
10460                    fn a() {
10461                        // b();
10462                        // c();
10463                        //  d();
10464                    }
10465                "
10466                .unindent()
10467            );
10468
10469            // If a selection ends at the beginning of a line, that line is not toggled.
10470            editor.change_selections(None, cx, |s| {
10471                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
10472            });
10473            editor.toggle_comments(&ToggleComments, cx);
10474            assert_eq!(
10475                editor.text(cx),
10476                "
10477                        fn a() {
10478                            // b();
10479                            c();
10480                            //  d();
10481                        }
10482                    "
10483                .unindent()
10484            );
10485        });
10486    }
10487
10488    #[gpui::test]
10489    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
10490        cx.set_global(Settings::test(cx));
10491        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10492        let multibuffer = cx.add_model(|cx| {
10493            let mut multibuffer = MultiBuffer::new(0);
10494            multibuffer.push_excerpts(
10495                buffer.clone(),
10496                [
10497                    ExcerptRange {
10498                        context: Point::new(0, 0)..Point::new(0, 4),
10499                        primary: None,
10500                    },
10501                    ExcerptRange {
10502                        context: Point::new(1, 0)..Point::new(1, 4),
10503                        primary: None,
10504                    },
10505                ],
10506                cx,
10507            );
10508            multibuffer
10509        });
10510
10511        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
10512
10513        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10514        view.update(cx, |view, cx| {
10515            assert_eq!(view.text(cx), "aaaa\nbbbb");
10516            view.change_selections(None, cx, |s| {
10517                s.select_ranges([
10518                    Point::new(0, 0)..Point::new(0, 0),
10519                    Point::new(1, 0)..Point::new(1, 0),
10520                ])
10521            });
10522
10523            view.handle_input("X", cx);
10524            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
10525            assert_eq!(
10526                view.selections.ranges(cx),
10527                [
10528                    Point::new(0, 1)..Point::new(0, 1),
10529                    Point::new(1, 1)..Point::new(1, 1),
10530                ]
10531            )
10532        });
10533    }
10534
10535    #[gpui::test]
10536    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
10537        cx.set_global(Settings::test(cx));
10538        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
10539                [aaaa
10540                (bbbb]
10541                cccc)"});
10542        let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
10543            context,
10544            primary: None,
10545        });
10546        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
10547        let multibuffer = cx.add_model(|cx| {
10548            let mut multibuffer = MultiBuffer::new(0);
10549            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
10550            multibuffer
10551        });
10552
10553        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10554        view.update(cx, |view, cx| {
10555            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
10556                aaaa
10557                b|bbb
10558                b|bb|b
10559                cccc"});
10560            assert_eq!(view.text(cx), expected_text);
10561            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
10562
10563            view.handle_input("X", cx);
10564
10565            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10566                aaaa
10567                bX|bbXb
10568                bX|bbX|b
10569                cccc"});
10570            assert_eq!(view.text(cx), expected_text);
10571            assert_eq!(view.selections.ranges(cx), expected_selections);
10572
10573            view.newline(&Newline, cx);
10574            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
10575                aaaa
10576                bX
10577                |bbX
10578                b
10579                bX
10580                |bbX
10581                |b
10582                cccc"});
10583            assert_eq!(view.text(cx), expected_text);
10584            assert_eq!(view.selections.ranges(cx), expected_selections);
10585        });
10586    }
10587
10588    #[gpui::test]
10589    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
10590        cx.set_global(Settings::test(cx));
10591        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10592        let mut excerpt1_id = None;
10593        let multibuffer = cx.add_model(|cx| {
10594            let mut multibuffer = MultiBuffer::new(0);
10595            excerpt1_id = multibuffer
10596                .push_excerpts(
10597                    buffer.clone(),
10598                    [
10599                        ExcerptRange {
10600                            context: Point::new(0, 0)..Point::new(1, 4),
10601                            primary: None,
10602                        },
10603                        ExcerptRange {
10604                            context: Point::new(1, 0)..Point::new(2, 4),
10605                            primary: None,
10606                        },
10607                    ],
10608                    cx,
10609                )
10610                .into_iter()
10611                .next();
10612            multibuffer
10613        });
10614        assert_eq!(
10615            multibuffer.read(cx).read(cx).text(),
10616            "aaaa\nbbbb\nbbbb\ncccc"
10617        );
10618        let (_, editor) = cx.add_window(Default::default(), |cx| {
10619            let mut editor = build_editor(multibuffer.clone(), cx);
10620            let snapshot = editor.snapshot(cx);
10621            editor.change_selections(None, cx, |s| {
10622                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
10623            });
10624            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
10625            assert_eq!(
10626                editor.selections.ranges(cx),
10627                [
10628                    Point::new(1, 3)..Point::new(1, 3),
10629                    Point::new(2, 1)..Point::new(2, 1),
10630                ]
10631            );
10632            editor
10633        });
10634
10635        // Refreshing selections is a no-op when excerpts haven't changed.
10636        editor.update(cx, |editor, cx| {
10637            editor.change_selections(None, cx, |s| {
10638                s.refresh();
10639            });
10640            assert_eq!(
10641                editor.selections.ranges(cx),
10642                [
10643                    Point::new(1, 3)..Point::new(1, 3),
10644                    Point::new(2, 1)..Point::new(2, 1),
10645                ]
10646            );
10647        });
10648
10649        multibuffer.update(cx, |multibuffer, cx| {
10650            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10651        });
10652        editor.update(cx, |editor, cx| {
10653            // Removing an excerpt causes the first selection to become degenerate.
10654            assert_eq!(
10655                editor.selections.ranges(cx),
10656                [
10657                    Point::new(0, 0)..Point::new(0, 0),
10658                    Point::new(0, 1)..Point::new(0, 1)
10659                ]
10660            );
10661
10662            // Refreshing selections will relocate the first selection to the original buffer
10663            // location.
10664            editor.change_selections(None, cx, |s| {
10665                s.refresh();
10666            });
10667            assert_eq!(
10668                editor.selections.ranges(cx),
10669                [
10670                    Point::new(0, 1)..Point::new(0, 1),
10671                    Point::new(0, 3)..Point::new(0, 3)
10672                ]
10673            );
10674            assert!(editor.selections.pending_anchor().is_some());
10675        });
10676    }
10677
10678    #[gpui::test]
10679    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10680        cx.set_global(Settings::test(cx));
10681        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10682        let mut excerpt1_id = None;
10683        let multibuffer = cx.add_model(|cx| {
10684            let mut multibuffer = MultiBuffer::new(0);
10685            excerpt1_id = multibuffer
10686                .push_excerpts(
10687                    buffer.clone(),
10688                    [
10689                        ExcerptRange {
10690                            context: Point::new(0, 0)..Point::new(1, 4),
10691                            primary: None,
10692                        },
10693                        ExcerptRange {
10694                            context: Point::new(1, 0)..Point::new(2, 4),
10695                            primary: None,
10696                        },
10697                    ],
10698                    cx,
10699                )
10700                .into_iter()
10701                .next();
10702            multibuffer
10703        });
10704        assert_eq!(
10705            multibuffer.read(cx).read(cx).text(),
10706            "aaaa\nbbbb\nbbbb\ncccc"
10707        );
10708        let (_, editor) = cx.add_window(Default::default(), |cx| {
10709            let mut editor = build_editor(multibuffer.clone(), cx);
10710            let snapshot = editor.snapshot(cx);
10711            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10712            assert_eq!(
10713                editor.selections.ranges(cx),
10714                [Point::new(1, 3)..Point::new(1, 3)]
10715            );
10716            editor
10717        });
10718
10719        multibuffer.update(cx, |multibuffer, cx| {
10720            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10721        });
10722        editor.update(cx, |editor, cx| {
10723            assert_eq!(
10724                editor.selections.ranges(cx),
10725                [Point::new(0, 0)..Point::new(0, 0)]
10726            );
10727
10728            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10729            editor.change_selections(None, cx, |s| {
10730                s.refresh();
10731            });
10732            assert_eq!(
10733                editor.selections.ranges(cx),
10734                [Point::new(0, 3)..Point::new(0, 3)]
10735            );
10736            assert!(editor.selections.pending_anchor().is_some());
10737        });
10738    }
10739
10740    #[gpui::test]
10741    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10742        cx.update(|cx| cx.set_global(Settings::test(cx)));
10743        let language = Arc::new(
10744            Language::new(
10745                LanguageConfig {
10746                    brackets: vec![
10747                        BracketPair {
10748                            start: "{".to_string(),
10749                            end: "}".to_string(),
10750                            close: true,
10751                            newline: true,
10752                        },
10753                        BracketPair {
10754                            start: "/* ".to_string(),
10755                            end: " */".to_string(),
10756                            close: true,
10757                            newline: true,
10758                        },
10759                    ],
10760                    ..Default::default()
10761                },
10762                Some(tree_sitter_rust::language()),
10763            )
10764            .with_indents_query("")
10765            .unwrap(),
10766        );
10767
10768        let text = concat!(
10769            "{   }\n",     // Suppress rustfmt
10770            "  x\n",       //
10771            "  /*   */\n", //
10772            "x\n",         //
10773            "{{} }\n",     //
10774        );
10775
10776        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10777        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10778        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10779        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10780            .await;
10781
10782        view.update(cx, |view, cx| {
10783            view.change_selections(None, cx, |s| {
10784                s.select_display_ranges([
10785                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10786                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10787                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10788                ])
10789            });
10790            view.newline(&Newline, cx);
10791
10792            assert_eq!(
10793                view.buffer().read(cx).read(cx).text(),
10794                concat!(
10795                    "{ \n",    // Suppress rustfmt
10796                    "\n",      //
10797                    "}\n",     //
10798                    "  x\n",   //
10799                    "  /* \n", //
10800                    "  \n",    //
10801                    "  */\n",  //
10802                    "x\n",     //
10803                    "{{} \n",  //
10804                    "}\n",     //
10805                )
10806            );
10807        });
10808    }
10809
10810    #[gpui::test]
10811    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10812        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10813
10814        cx.set_global(Settings::test(cx));
10815        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10816
10817        editor.update(cx, |editor, cx| {
10818            struct Type1;
10819            struct Type2;
10820
10821            let buffer = buffer.read(cx).snapshot(cx);
10822
10823            let anchor_range = |range: Range<Point>| {
10824                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10825            };
10826
10827            editor.highlight_background::<Type1>(
10828                vec![
10829                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10830                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10831                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10832                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10833                ],
10834                |_| Color::red(),
10835                cx,
10836            );
10837            editor.highlight_background::<Type2>(
10838                vec![
10839                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10840                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10841                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10842                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10843                ],
10844                |_| Color::green(),
10845                cx,
10846            );
10847
10848            let snapshot = editor.snapshot(cx);
10849            let mut highlighted_ranges = editor.background_highlights_in_range(
10850                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10851                &snapshot,
10852                cx.global::<Settings>().theme.as_ref(),
10853            );
10854            // Enforce a consistent ordering based on color without relying on the ordering of the
10855            // highlight's `TypeId` which is non-deterministic.
10856            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10857            assert_eq!(
10858                highlighted_ranges,
10859                &[
10860                    (
10861                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10862                        Color::green(),
10863                    ),
10864                    (
10865                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10866                        Color::green(),
10867                    ),
10868                    (
10869                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10870                        Color::red(),
10871                    ),
10872                    (
10873                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10874                        Color::red(),
10875                    ),
10876                ]
10877            );
10878            assert_eq!(
10879                editor.background_highlights_in_range(
10880                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10881                    &snapshot,
10882                    cx.global::<Settings>().theme.as_ref(),
10883                ),
10884                &[(
10885                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10886                    Color::red(),
10887                )]
10888            );
10889        });
10890    }
10891
10892    #[gpui::test]
10893    fn test_following(cx: &mut gpui::MutableAppContext) {
10894        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10895
10896        cx.set_global(Settings::test(cx));
10897
10898        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10899        let (_, follower) = cx.add_window(
10900            WindowOptions {
10901                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10902                ..Default::default()
10903            },
10904            |cx| build_editor(buffer.clone(), cx),
10905        );
10906
10907        let pending_update = Rc::new(RefCell::new(None));
10908        follower.update(cx, {
10909            let update = pending_update.clone();
10910            |_, cx| {
10911                cx.subscribe(&leader, move |_, leader, event, cx| {
10912                    leader
10913                        .read(cx)
10914                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10915                })
10916                .detach();
10917            }
10918        });
10919
10920        // Update the selections only
10921        leader.update(cx, |leader, cx| {
10922            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10923        });
10924        follower.update(cx, |follower, cx| {
10925            follower
10926                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10927                .unwrap();
10928        });
10929        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
10930
10931        // Update the scroll position only
10932        leader.update(cx, |leader, cx| {
10933            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10934        });
10935        follower.update(cx, |follower, cx| {
10936            follower
10937                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10938                .unwrap();
10939        });
10940        assert_eq!(
10941            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10942            vec2f(1.5, 3.5)
10943        );
10944
10945        // Update the selections and scroll position
10946        leader.update(cx, |leader, cx| {
10947            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
10948            leader.request_autoscroll(Autoscroll::Newest, cx);
10949            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10950        });
10951        follower.update(cx, |follower, cx| {
10952            let initial_scroll_position = follower.scroll_position(cx);
10953            follower
10954                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10955                .unwrap();
10956            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10957            assert!(follower.autoscroll_request.is_some());
10958        });
10959        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
10960
10961        // Creating a pending selection that precedes another selection
10962        leader.update(cx, |leader, cx| {
10963            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10964            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10965        });
10966        follower.update(cx, |follower, cx| {
10967            follower
10968                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10969                .unwrap();
10970        });
10971        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
10972
10973        // Extend the pending selection so that it surrounds another selection
10974        leader.update(cx, |leader, cx| {
10975            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10976        });
10977        follower.update(cx, |follower, cx| {
10978            follower
10979                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10980                .unwrap();
10981        });
10982        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
10983    }
10984
10985    #[test]
10986    fn test_combine_syntax_and_fuzzy_match_highlights() {
10987        let string = "abcdefghijklmnop";
10988        let syntax_ranges = [
10989            (
10990                0..3,
10991                HighlightStyle {
10992                    color: Some(Color::red()),
10993                    ..Default::default()
10994                },
10995            ),
10996            (
10997                4..8,
10998                HighlightStyle {
10999                    color: Some(Color::green()),
11000                    ..Default::default()
11001                },
11002            ),
11003        ];
11004        let match_indices = [4, 6, 7, 8];
11005        assert_eq!(
11006            combine_syntax_and_fuzzy_match_highlights(
11007                &string,
11008                Default::default(),
11009                syntax_ranges.into_iter(),
11010                &match_indices,
11011            ),
11012            &[
11013                (
11014                    0..3,
11015                    HighlightStyle {
11016                        color: Some(Color::red()),
11017                        ..Default::default()
11018                    },
11019                ),
11020                (
11021                    4..5,
11022                    HighlightStyle {
11023                        color: Some(Color::green()),
11024                        weight: Some(fonts::Weight::BOLD),
11025                        ..Default::default()
11026                    },
11027                ),
11028                (
11029                    5..6,
11030                    HighlightStyle {
11031                        color: Some(Color::green()),
11032                        ..Default::default()
11033                    },
11034                ),
11035                (
11036                    6..8,
11037                    HighlightStyle {
11038                        color: Some(Color::green()),
11039                        weight: Some(fonts::Weight::BOLD),
11040                        ..Default::default()
11041                    },
11042                ),
11043                (
11044                    8..9,
11045                    HighlightStyle {
11046                        weight: Some(fonts::Weight::BOLD),
11047                        ..Default::default()
11048                    },
11049                ),
11050            ]
11051        );
11052    }
11053
11054    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
11055        let point = DisplayPoint::new(row as u32, column as u32);
11056        point..point
11057    }
11058
11059    fn assert_selection_ranges(
11060        marked_text: &str,
11061        selection_marker_pairs: Vec<(char, char)>,
11062        view: &mut Editor,
11063        cx: &mut ViewContext<Editor>,
11064    ) {
11065        let snapshot = view.snapshot(cx).display_snapshot;
11066        let mut marker_chars = Vec::new();
11067        for (start, end) in selection_marker_pairs.iter() {
11068            marker_chars.push(*start);
11069            marker_chars.push(*end);
11070        }
11071        let (_, markers) = marked_text_by(marked_text, marker_chars);
11072        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
11073            .iter()
11074            .map(|(start, end)| {
11075                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
11076                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
11077                start..end
11078            })
11079            .collect();
11080        assert_eq!(
11081            view.selections.display_ranges(cx),
11082            &asserted_ranges[..],
11083            "Assert selections are {}",
11084            marked_text
11085        );
11086    }
11087}
11088
11089trait RangeExt<T> {
11090    fn sorted(&self) -> Range<T>;
11091    fn to_inclusive(&self) -> RangeInclusive<T>;
11092}
11093
11094impl<T: Ord + Clone> RangeExt<T> for Range<T> {
11095    fn sorted(&self) -> Self {
11096        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
11097    }
11098
11099    fn to_inclusive(&self) -> RangeInclusive<T> {
11100        self.start.clone()..=self.end.clone()
11101    }
11102}
11103
11104trait RangeToAnchorExt {
11105    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
11106}
11107
11108impl<T: ToOffset> RangeToAnchorExt for Range<T> {
11109    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
11110        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
11111    }
11112}