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