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