editor.rs

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