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