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