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