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