editor.rs

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