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