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::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
 6648    };
 6649    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6650
 6651    #[gpui::test]
 6652    fn test_edit_events(cx: &mut MutableAppContext) {
 6653        cx.set_global(Settings::test(cx));
 6654        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6655
 6656        let events = Rc::new(RefCell::new(Vec::new()));
 6657        let (_, editor1) = cx.add_window(Default::default(), {
 6658            let events = events.clone();
 6659            |cx| {
 6660                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6661                    if matches!(
 6662                        event,
 6663                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6664                    ) {
 6665                        events.borrow_mut().push(("editor1", *event));
 6666                    }
 6667                })
 6668                .detach();
 6669                Editor::for_buffer(buffer.clone(), None, cx)
 6670            }
 6671        });
 6672        let (_, editor2) = cx.add_window(Default::default(), {
 6673            let events = events.clone();
 6674            |cx| {
 6675                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6676                    if matches!(
 6677                        event,
 6678                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6679                    ) {
 6680                        events.borrow_mut().push(("editor2", *event));
 6681                    }
 6682                })
 6683                .detach();
 6684                Editor::for_buffer(buffer.clone(), None, cx)
 6685            }
 6686        });
 6687        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6688
 6689        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6690        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6691        assert_eq!(
 6692            mem::take(&mut *events.borrow_mut()),
 6693            [
 6694                ("editor1", Event::Edited),
 6695                ("editor1", Event::BufferEdited),
 6696                ("editor2", Event::BufferEdited),
 6697                ("editor1", Event::DirtyChanged),
 6698                ("editor2", Event::DirtyChanged)
 6699            ]
 6700        );
 6701
 6702        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6703        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6704        assert_eq!(
 6705            mem::take(&mut *events.borrow_mut()),
 6706            [
 6707                ("editor2", Event::Edited),
 6708                ("editor1", Event::BufferEdited),
 6709                ("editor2", Event::BufferEdited),
 6710            ]
 6711        );
 6712
 6713        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6714        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6715        assert_eq!(
 6716            mem::take(&mut *events.borrow_mut()),
 6717            [
 6718                ("editor1", Event::Edited),
 6719                ("editor1", Event::BufferEdited),
 6720                ("editor2", Event::BufferEdited),
 6721                ("editor1", Event::DirtyChanged),
 6722                ("editor2", Event::DirtyChanged),
 6723            ]
 6724        );
 6725
 6726        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6727        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6728        assert_eq!(
 6729            mem::take(&mut *events.borrow_mut()),
 6730            [
 6731                ("editor1", Event::Edited),
 6732                ("editor1", Event::BufferEdited),
 6733                ("editor2", Event::BufferEdited),
 6734                ("editor1", Event::DirtyChanged),
 6735                ("editor2", Event::DirtyChanged),
 6736            ]
 6737        );
 6738
 6739        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6740        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6741        assert_eq!(
 6742            mem::take(&mut *events.borrow_mut()),
 6743            [
 6744                ("editor2", Event::Edited),
 6745                ("editor1", Event::BufferEdited),
 6746                ("editor2", Event::BufferEdited),
 6747                ("editor1", Event::DirtyChanged),
 6748                ("editor2", Event::DirtyChanged),
 6749            ]
 6750        );
 6751
 6752        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6753        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6754        assert_eq!(
 6755            mem::take(&mut *events.borrow_mut()),
 6756            [
 6757                ("editor2", Event::Edited),
 6758                ("editor1", Event::BufferEdited),
 6759                ("editor2", Event::BufferEdited),
 6760                ("editor1", Event::DirtyChanged),
 6761                ("editor2", Event::DirtyChanged),
 6762            ]
 6763        );
 6764
 6765        // No event is emitted when the mutation is a no-op.
 6766        editor2.update(cx, |editor, cx| {
 6767            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6768
 6769            editor.backspace(&Backspace, cx);
 6770        });
 6771        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6772    }
 6773
 6774    #[gpui::test]
 6775    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6776        cx.set_global(Settings::test(cx));
 6777        let mut now = Instant::now();
 6778        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6779        let group_interval = buffer.read(cx).transaction_group_interval();
 6780        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6781        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6782
 6783        editor.update(cx, |editor, cx| {
 6784            editor.start_transaction_at(now, cx);
 6785            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6786
 6787            editor.insert("cd", cx);
 6788            editor.end_transaction_at(now, cx);
 6789            assert_eq!(editor.text(cx), "12cd56");
 6790            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6791
 6792            editor.start_transaction_at(now, cx);
 6793            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6794            editor.insert("e", cx);
 6795            editor.end_transaction_at(now, cx);
 6796            assert_eq!(editor.text(cx), "12cde6");
 6797            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6798
 6799            now += group_interval + Duration::from_millis(1);
 6800            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6801
 6802            // Simulate an edit in another editor
 6803            buffer.update(cx, |buffer, cx| {
 6804                buffer.start_transaction_at(now, cx);
 6805                buffer.edit([(0..1, "a")], None, cx);
 6806                buffer.edit([(1..1, "b")], None, cx);
 6807                buffer.end_transaction_at(now, cx);
 6808            });
 6809
 6810            assert_eq!(editor.text(cx), "ab2cde6");
 6811            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6812
 6813            // Last transaction happened past the group interval in a different editor.
 6814            // Undo it individually and don't restore selections.
 6815            editor.undo(&Undo, cx);
 6816            assert_eq!(editor.text(cx), "12cde6");
 6817            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6818
 6819            // First two transactions happened within the group interval in this editor.
 6820            // Undo them together and restore selections.
 6821            editor.undo(&Undo, cx);
 6822            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6823            assert_eq!(editor.text(cx), "123456");
 6824            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6825
 6826            // Redo the first two transactions together.
 6827            editor.redo(&Redo, cx);
 6828            assert_eq!(editor.text(cx), "12cde6");
 6829            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6830
 6831            // Redo the last transaction on its own.
 6832            editor.redo(&Redo, cx);
 6833            assert_eq!(editor.text(cx), "ab2cde6");
 6834            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6835
 6836            // Test empty transactions.
 6837            editor.start_transaction_at(now, cx);
 6838            editor.end_transaction_at(now, cx);
 6839            editor.undo(&Undo, cx);
 6840            assert_eq!(editor.text(cx), "12cde6");
 6841        });
 6842    }
 6843
 6844    #[gpui::test]
 6845    fn test_ime_composition(cx: &mut MutableAppContext) {
 6846        cx.set_global(Settings::test(cx));
 6847        let buffer = cx.add_model(|cx| {
 6848            let mut buffer = language::Buffer::new(0, "abcde", cx);
 6849            // Ensure automatic grouping doesn't occur.
 6850            buffer.set_group_interval(Duration::ZERO);
 6851            buffer
 6852        });
 6853
 6854        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6855        cx.add_window(Default::default(), |cx| {
 6856            let mut editor = build_editor(buffer.clone(), cx);
 6857
 6858            // Start a new IME composition.
 6859            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6860            editor.replace_and_mark_text_in_range(Some(0..1), "á", None, cx);
 6861            editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
 6862            assert_eq!(editor.text(cx), "äbcde");
 6863            assert_eq!(
 6864                editor.marked_text_ranges(cx),
 6865                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6866            );
 6867
 6868            // Finalize IME composition.
 6869            editor.replace_text_in_range(None, "ā", cx);
 6870            assert_eq!(editor.text(cx), "ābcde");
 6871            assert_eq!(editor.marked_text_ranges(cx), None);
 6872
 6873            // IME composition edits are grouped and are undone/redone at once.
 6874            editor.undo(&Default::default(), cx);
 6875            assert_eq!(editor.text(cx), "abcde");
 6876            assert_eq!(editor.marked_text_ranges(cx), None);
 6877            editor.redo(&Default::default(), cx);
 6878            assert_eq!(editor.text(cx), "ābcde");
 6879            assert_eq!(editor.marked_text_ranges(cx), None);
 6880
 6881            // Start a new IME composition.
 6882            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6883            assert_eq!(
 6884                editor.marked_text_ranges(cx),
 6885                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6886            );
 6887
 6888            // Undoing during an IME composition cancels it.
 6889            editor.undo(&Default::default(), cx);
 6890            assert_eq!(editor.text(cx), "ābcde");
 6891            assert_eq!(editor.marked_text_ranges(cx), None);
 6892
 6893            // Start a new IME composition with an invalid marked range, ensuring it gets clipped.
 6894            editor.replace_and_mark_text_in_range(Some(4..999), "è", None, cx);
 6895            assert_eq!(editor.text(cx), "ābcdè");
 6896            assert_eq!(
 6897                editor.marked_text_ranges(cx),
 6898                Some(vec![OffsetUtf16(4)..OffsetUtf16(5)])
 6899            );
 6900
 6901            // Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
 6902            editor.replace_text_in_range(Some(4..999), "ę", cx);
 6903            assert_eq!(editor.text(cx), "ābcdę");
 6904            assert_eq!(editor.marked_text_ranges(cx), None);
 6905
 6906            // Start a new IME composition with multiple cursors.
 6907            editor.change_selections(None, cx, |s| {
 6908                s.select_ranges([
 6909                    OffsetUtf16(1)..OffsetUtf16(1),
 6910                    OffsetUtf16(3)..OffsetUtf16(3),
 6911                    OffsetUtf16(5)..OffsetUtf16(5),
 6912                ])
 6913            });
 6914            editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, cx);
 6915            assert_eq!(editor.text(cx), "XYZbXYZdXYZ");
 6916            assert_eq!(
 6917                editor.marked_text_ranges(cx),
 6918                Some(vec![
 6919                    OffsetUtf16(0)..OffsetUtf16(3),
 6920                    OffsetUtf16(4)..OffsetUtf16(7),
 6921                    OffsetUtf16(8)..OffsetUtf16(11)
 6922                ])
 6923            );
 6924
 6925            // Ensure the newly-marked range gets treated as relative to the previously-marked ranges.
 6926            editor.replace_and_mark_text_in_range(Some(1..2), "1", None, cx);
 6927            assert_eq!(editor.text(cx), "X1ZbX1ZdX1Z");
 6928            assert_eq!(
 6929                editor.marked_text_ranges(cx),
 6930                Some(vec![
 6931                    OffsetUtf16(1)..OffsetUtf16(2),
 6932                    OffsetUtf16(5)..OffsetUtf16(6),
 6933                    OffsetUtf16(9)..OffsetUtf16(10)
 6934                ])
 6935            );
 6936
 6937            // Finalize IME composition with multiple cursors.
 6938            editor.replace_text_in_range(Some(9..10), "2", cx);
 6939            assert_eq!(editor.text(cx), "X2ZbX2ZdX2Z");
 6940            assert_eq!(editor.marked_text_ranges(cx), None);
 6941
 6942            editor
 6943        });
 6944    }
 6945
 6946    #[gpui::test]
 6947    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6948        cx.set_global(Settings::test(cx));
 6949
 6950        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6951        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6952        editor.update(cx, |view, cx| {
 6953            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6954        });
 6955        assert_eq!(
 6956            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6957            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6958        );
 6959
 6960        editor.update(cx, |view, cx| {
 6961            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6962        });
 6963
 6964        assert_eq!(
 6965            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6966            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6967        );
 6968
 6969        editor.update(cx, |view, cx| {
 6970            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6971        });
 6972
 6973        assert_eq!(
 6974            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6975            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6976        );
 6977
 6978        editor.update(cx, |view, cx| {
 6979            view.end_selection(cx);
 6980            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6981        });
 6982
 6983        assert_eq!(
 6984            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6985            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6986        );
 6987
 6988        editor.update(cx, |view, cx| {
 6989            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6990            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6991        });
 6992
 6993        assert_eq!(
 6994            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6995            [
 6996                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6997                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6998            ]
 6999        );
 7000
 7001        editor.update(cx, |view, cx| {
 7002            view.end_selection(cx);
 7003        });
 7004
 7005        assert_eq!(
 7006            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7007            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 7008        );
 7009    }
 7010
 7011    #[gpui::test]
 7012    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 7013        cx.set_global(Settings::test(cx));
 7014        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7015        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7016
 7017        view.update(cx, |view, cx| {
 7018            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 7019            assert_eq!(
 7020                view.selections.display_ranges(cx),
 7021                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 7022            );
 7023        });
 7024
 7025        view.update(cx, |view, cx| {
 7026            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7027            assert_eq!(
 7028                view.selections.display_ranges(cx),
 7029                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7030            );
 7031        });
 7032
 7033        view.update(cx, |view, cx| {
 7034            view.cancel(&Cancel, cx);
 7035            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7036            assert_eq!(
 7037                view.selections.display_ranges(cx),
 7038                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7039            );
 7040        });
 7041    }
 7042
 7043    #[gpui::test]
 7044    fn test_clone(cx: &mut gpui::MutableAppContext) {
 7045        let (text, selection_ranges) = marked_text_ranges(
 7046            indoc! {"
 7047                one
 7048                two
 7049                threeˇ
 7050                four
 7051                fiveˇ
 7052            "},
 7053            true,
 7054        );
 7055        cx.set_global(Settings::test(cx));
 7056        let buffer = MultiBuffer::build_simple(&text, cx);
 7057
 7058        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7059
 7060        editor.update(cx, |editor, cx| {
 7061            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 7062            editor.fold_ranges(
 7063                [
 7064                    Point::new(1, 0)..Point::new(2, 0),
 7065                    Point::new(3, 0)..Point::new(4, 0),
 7066                ],
 7067                cx,
 7068            );
 7069        });
 7070
 7071        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 7072            cx.add_window(Default::default(), |cx| editor.clone(cx))
 7073        });
 7074
 7075        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 7076        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 7077
 7078        assert_eq!(
 7079            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 7080            editor.update(cx, |e, cx| e.display_text(cx))
 7081        );
 7082        assert_eq!(
 7083            cloned_snapshot
 7084                .folds_in_range(0..text.len())
 7085                .collect::<Vec<_>>(),
 7086            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 7087        );
 7088        assert_set_eq!(
 7089            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 7090            editor.read(cx).selections.ranges(cx)
 7091        );
 7092        assert_set_eq!(
 7093            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 7094            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 7095        );
 7096    }
 7097
 7098    #[gpui::test]
 7099    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 7100        cx.set_global(Settings::test(cx));
 7101        use workspace::Item;
 7102        let pane = cx.add_view(Default::default(), |cx| Pane::new(cx));
 7103        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 7104
 7105        cx.add_window(Default::default(), |cx| {
 7106            let mut editor = build_editor(buffer.clone(), cx);
 7107            let handle = cx.handle();
 7108            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 7109
 7110            fn pop_history(
 7111                editor: &mut Editor,
 7112                cx: &mut MutableAppContext,
 7113            ) -> Option<NavigationEntry> {
 7114                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 7115            }
 7116
 7117            // Move the cursor a small distance.
 7118            // Nothing is added to the navigation history.
 7119            editor.change_selections(None, cx, |s| {
 7120                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 7121            });
 7122            editor.change_selections(None, cx, |s| {
 7123                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 7124            });
 7125            assert!(pop_history(&mut editor, cx).is_none());
 7126
 7127            // Move the cursor a large distance.
 7128            // The history can jump back to the previous position.
 7129            editor.change_selections(None, cx, |s| {
 7130                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 7131            });
 7132            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7133            editor.navigate(nav_entry.data.unwrap(), cx);
 7134            assert_eq!(nav_entry.item.id(), cx.view_id());
 7135            assert_eq!(
 7136                editor.selections.display_ranges(cx),
 7137                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 7138            );
 7139            assert!(pop_history(&mut editor, cx).is_none());
 7140
 7141            // Move the cursor a small distance via the mouse.
 7142            // Nothing is added to the navigation history.
 7143            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 7144            editor.end_selection(cx);
 7145            assert_eq!(
 7146                editor.selections.display_ranges(cx),
 7147                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7148            );
 7149            assert!(pop_history(&mut editor, cx).is_none());
 7150
 7151            // Move the cursor a large distance via the mouse.
 7152            // The history can jump back to the previous position.
 7153            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 7154            editor.end_selection(cx);
 7155            assert_eq!(
 7156                editor.selections.display_ranges(cx),
 7157                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 7158            );
 7159            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7160            editor.navigate(nav_entry.data.unwrap(), cx);
 7161            assert_eq!(nav_entry.item.id(), cx.view_id());
 7162            assert_eq!(
 7163                editor.selections.display_ranges(cx),
 7164                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7165            );
 7166            assert!(pop_history(&mut editor, cx).is_none());
 7167
 7168            // Set scroll position to check later
 7169            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 7170            let original_scroll_position = editor.scroll_position;
 7171            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 7172
 7173            // Jump to the end of the document and adjust scroll
 7174            editor.move_to_end(&MoveToEnd, cx);
 7175            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 7176            assert_ne!(editor.scroll_position, original_scroll_position);
 7177            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7178
 7179            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7180            editor.navigate(nav_entry.data.unwrap(), cx);
 7181            assert_eq!(editor.scroll_position, original_scroll_position);
 7182            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7183
 7184            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 7185            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 7186            invalid_anchor.text_anchor.buffer_id = Some(999);
 7187            let invalid_point = Point::new(9999, 0);
 7188            editor.navigate(
 7189                Box::new(NavigationData {
 7190                    cursor_anchor: invalid_anchor.clone(),
 7191                    cursor_position: invalid_point,
 7192                    scroll_top_anchor: invalid_anchor.clone(),
 7193                    scroll_top_row: invalid_point.row,
 7194                    scroll_position: Default::default(),
 7195                }),
 7196                cx,
 7197            );
 7198            assert_eq!(
 7199                editor.selections.display_ranges(cx),
 7200                &[editor.max_point(cx)..editor.max_point(cx)]
 7201            );
 7202            assert_eq!(
 7203                editor.scroll_position(cx),
 7204                vec2f(0., editor.max_point(cx).row() as f32)
 7205            );
 7206
 7207            editor
 7208        });
 7209    }
 7210
 7211    #[gpui::test]
 7212    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 7213        cx.set_global(Settings::test(cx));
 7214        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7215        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7216
 7217        view.update(cx, |view, cx| {
 7218            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 7219            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7220            view.end_selection(cx);
 7221
 7222            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 7223            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 7224            view.end_selection(cx);
 7225            assert_eq!(
 7226                view.selections.display_ranges(cx),
 7227                [
 7228                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 7229                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 7230                ]
 7231            );
 7232        });
 7233
 7234        view.update(cx, |view, cx| {
 7235            view.cancel(&Cancel, cx);
 7236            assert_eq!(
 7237                view.selections.display_ranges(cx),
 7238                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 7239            );
 7240        });
 7241
 7242        view.update(cx, |view, cx| {
 7243            view.cancel(&Cancel, cx);
 7244            assert_eq!(
 7245                view.selections.display_ranges(cx),
 7246                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 7247            );
 7248        });
 7249    }
 7250
 7251    #[gpui::test]
 7252    fn test_fold(cx: &mut gpui::MutableAppContext) {
 7253        cx.set_global(Settings::test(cx));
 7254        let buffer = MultiBuffer::build_simple(
 7255            &"
 7256                impl Foo {
 7257                    // Hello!
 7258
 7259                    fn a() {
 7260                        1
 7261                    }
 7262
 7263                    fn b() {
 7264                        2
 7265                    }
 7266
 7267                    fn c() {
 7268                        3
 7269                    }
 7270                }
 7271            "
 7272            .unindent(),
 7273            cx,
 7274        );
 7275        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7276
 7277        view.update(cx, |view, cx| {
 7278            view.change_selections(None, cx, |s| {
 7279                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 7280            });
 7281            view.fold(&Fold, cx);
 7282            assert_eq!(
 7283                view.display_text(cx),
 7284                "
 7285                    impl Foo {
 7286                        // Hello!
 7287
 7288                        fn a() {
 7289                            1
 7290                        }
 7291
 7292                        fn b() {…
 7293                        }
 7294
 7295                        fn c() {…
 7296                        }
 7297                    }
 7298                "
 7299                .unindent(),
 7300            );
 7301
 7302            view.fold(&Fold, cx);
 7303            assert_eq!(
 7304                view.display_text(cx),
 7305                "
 7306                    impl Foo {…
 7307                    }
 7308                "
 7309                .unindent(),
 7310            );
 7311
 7312            view.unfold_lines(&UnfoldLines, cx);
 7313            assert_eq!(
 7314                view.display_text(cx),
 7315                "
 7316                    impl Foo {
 7317                        // Hello!
 7318
 7319                        fn a() {
 7320                            1
 7321                        }
 7322
 7323                        fn b() {…
 7324                        }
 7325
 7326                        fn c() {…
 7327                        }
 7328                    }
 7329                "
 7330                .unindent(),
 7331            );
 7332
 7333            view.unfold_lines(&UnfoldLines, cx);
 7334            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7335        });
 7336    }
 7337
 7338    #[gpui::test]
 7339    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7340        cx.set_global(Settings::test(cx));
 7341        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7342        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7343
 7344        buffer.update(cx, |buffer, cx| {
 7345            buffer.edit(
 7346                vec![
 7347                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7348                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7349                ],
 7350                None,
 7351                cx,
 7352            );
 7353        });
 7354
 7355        view.update(cx, |view, cx| {
 7356            assert_eq!(
 7357                view.selections.display_ranges(cx),
 7358                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7359            );
 7360
 7361            view.move_down(&MoveDown, cx);
 7362            assert_eq!(
 7363                view.selections.display_ranges(cx),
 7364                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7365            );
 7366
 7367            view.move_right(&MoveRight, cx);
 7368            assert_eq!(
 7369                view.selections.display_ranges(cx),
 7370                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7371            );
 7372
 7373            view.move_left(&MoveLeft, cx);
 7374            assert_eq!(
 7375                view.selections.display_ranges(cx),
 7376                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7377            );
 7378
 7379            view.move_up(&MoveUp, cx);
 7380            assert_eq!(
 7381                view.selections.display_ranges(cx),
 7382                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7383            );
 7384
 7385            view.move_to_end(&MoveToEnd, cx);
 7386            assert_eq!(
 7387                view.selections.display_ranges(cx),
 7388                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7389            );
 7390
 7391            view.move_to_beginning(&MoveToBeginning, cx);
 7392            assert_eq!(
 7393                view.selections.display_ranges(cx),
 7394                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7395            );
 7396
 7397            view.change_selections(None, cx, |s| {
 7398                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 7399            });
 7400            view.select_to_beginning(&SelectToBeginning, cx);
 7401            assert_eq!(
 7402                view.selections.display_ranges(cx),
 7403                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7404            );
 7405
 7406            view.select_to_end(&SelectToEnd, cx);
 7407            assert_eq!(
 7408                view.selections.display_ranges(cx),
 7409                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7410            );
 7411        });
 7412    }
 7413
 7414    #[gpui::test]
 7415    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7416        cx.set_global(Settings::test(cx));
 7417        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7418        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7419
 7420        assert_eq!('ⓐ'.len_utf8(), 3);
 7421        assert_eq!('α'.len_utf8(), 2);
 7422
 7423        view.update(cx, |view, cx| {
 7424            view.fold_ranges(
 7425                vec![
 7426                    Point::new(0, 6)..Point::new(0, 12),
 7427                    Point::new(1, 2)..Point::new(1, 4),
 7428                    Point::new(2, 4)..Point::new(2, 8),
 7429                ],
 7430                cx,
 7431            );
 7432            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7433
 7434            view.move_right(&MoveRight, cx);
 7435            assert_eq!(
 7436                view.selections.display_ranges(cx),
 7437                &[empty_range(0, "".len())]
 7438            );
 7439            view.move_right(&MoveRight, cx);
 7440            assert_eq!(
 7441                view.selections.display_ranges(cx),
 7442                &[empty_range(0, "ⓐⓑ".len())]
 7443            );
 7444            view.move_right(&MoveRight, cx);
 7445            assert_eq!(
 7446                view.selections.display_ranges(cx),
 7447                &[empty_range(0, "ⓐⓑ…".len())]
 7448            );
 7449
 7450            view.move_down(&MoveDown, cx);
 7451            assert_eq!(
 7452                view.selections.display_ranges(cx),
 7453                &[empty_range(1, "ab…".len())]
 7454            );
 7455            view.move_left(&MoveLeft, cx);
 7456            assert_eq!(
 7457                view.selections.display_ranges(cx),
 7458                &[empty_range(1, "ab".len())]
 7459            );
 7460            view.move_left(&MoveLeft, cx);
 7461            assert_eq!(
 7462                view.selections.display_ranges(cx),
 7463                &[empty_range(1, "a".len())]
 7464            );
 7465
 7466            view.move_down(&MoveDown, cx);
 7467            assert_eq!(
 7468                view.selections.display_ranges(cx),
 7469                &[empty_range(2, "α".len())]
 7470            );
 7471            view.move_right(&MoveRight, cx);
 7472            assert_eq!(
 7473                view.selections.display_ranges(cx),
 7474                &[empty_range(2, "αβ".len())]
 7475            );
 7476            view.move_right(&MoveRight, cx);
 7477            assert_eq!(
 7478                view.selections.display_ranges(cx),
 7479                &[empty_range(2, "αβ…".len())]
 7480            );
 7481            view.move_right(&MoveRight, cx);
 7482            assert_eq!(
 7483                view.selections.display_ranges(cx),
 7484                &[empty_range(2, "αβ…ε".len())]
 7485            );
 7486
 7487            view.move_up(&MoveUp, cx);
 7488            assert_eq!(
 7489                view.selections.display_ranges(cx),
 7490                &[empty_range(1, "ab…e".len())]
 7491            );
 7492            view.move_up(&MoveUp, cx);
 7493            assert_eq!(
 7494                view.selections.display_ranges(cx),
 7495                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7496            );
 7497            view.move_left(&MoveLeft, cx);
 7498            assert_eq!(
 7499                view.selections.display_ranges(cx),
 7500                &[empty_range(0, "ⓐⓑ…".len())]
 7501            );
 7502            view.move_left(&MoveLeft, cx);
 7503            assert_eq!(
 7504                view.selections.display_ranges(cx),
 7505                &[empty_range(0, "ⓐⓑ".len())]
 7506            );
 7507            view.move_left(&MoveLeft, cx);
 7508            assert_eq!(
 7509                view.selections.display_ranges(cx),
 7510                &[empty_range(0, "".len())]
 7511            );
 7512        });
 7513    }
 7514
 7515    #[gpui::test]
 7516    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7517        cx.set_global(Settings::test(cx));
 7518        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7519        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7520        view.update(cx, |view, cx| {
 7521            view.change_selections(None, cx, |s| {
 7522                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7523            });
 7524            view.move_down(&MoveDown, cx);
 7525            assert_eq!(
 7526                view.selections.display_ranges(cx),
 7527                &[empty_range(1, "abcd".len())]
 7528            );
 7529
 7530            view.move_down(&MoveDown, cx);
 7531            assert_eq!(
 7532                view.selections.display_ranges(cx),
 7533                &[empty_range(2, "αβγ".len())]
 7534            );
 7535
 7536            view.move_down(&MoveDown, cx);
 7537            assert_eq!(
 7538                view.selections.display_ranges(cx),
 7539                &[empty_range(3, "abcd".len())]
 7540            );
 7541
 7542            view.move_down(&MoveDown, cx);
 7543            assert_eq!(
 7544                view.selections.display_ranges(cx),
 7545                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7546            );
 7547
 7548            view.move_up(&MoveUp, cx);
 7549            assert_eq!(
 7550                view.selections.display_ranges(cx),
 7551                &[empty_range(3, "abcd".len())]
 7552            );
 7553
 7554            view.move_up(&MoveUp, cx);
 7555            assert_eq!(
 7556                view.selections.display_ranges(cx),
 7557                &[empty_range(2, "αβγ".len())]
 7558            );
 7559        });
 7560    }
 7561
 7562    #[gpui::test]
 7563    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7564        cx.set_global(Settings::test(cx));
 7565        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7566        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7567        view.update(cx, |view, cx| {
 7568            view.change_selections(None, cx, |s| {
 7569                s.select_display_ranges([
 7570                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7571                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7572                ]);
 7573            });
 7574        });
 7575
 7576        view.update(cx, |view, cx| {
 7577            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7578            assert_eq!(
 7579                view.selections.display_ranges(cx),
 7580                &[
 7581                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7582                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7583                ]
 7584            );
 7585        });
 7586
 7587        view.update(cx, |view, cx| {
 7588            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7589            assert_eq!(
 7590                view.selections.display_ranges(cx),
 7591                &[
 7592                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7593                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7594                ]
 7595            );
 7596        });
 7597
 7598        view.update(cx, |view, cx| {
 7599            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7600            assert_eq!(
 7601                view.selections.display_ranges(cx),
 7602                &[
 7603                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7604                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7605                ]
 7606            );
 7607        });
 7608
 7609        view.update(cx, |view, cx| {
 7610            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7611            assert_eq!(
 7612                view.selections.display_ranges(cx),
 7613                &[
 7614                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7615                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7616                ]
 7617            );
 7618        });
 7619
 7620        // Moving to the end of line again is a no-op.
 7621        view.update(cx, |view, cx| {
 7622            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7623            assert_eq!(
 7624                view.selections.display_ranges(cx),
 7625                &[
 7626                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7627                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7628                ]
 7629            );
 7630        });
 7631
 7632        view.update(cx, |view, cx| {
 7633            view.move_left(&MoveLeft, cx);
 7634            view.select_to_beginning_of_line(
 7635                &SelectToBeginningOfLine {
 7636                    stop_at_soft_wraps: true,
 7637                },
 7638                cx,
 7639            );
 7640            assert_eq!(
 7641                view.selections.display_ranges(cx),
 7642                &[
 7643                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7644                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7645                ]
 7646            );
 7647        });
 7648
 7649        view.update(cx, |view, cx| {
 7650            view.select_to_beginning_of_line(
 7651                &SelectToBeginningOfLine {
 7652                    stop_at_soft_wraps: true,
 7653                },
 7654                cx,
 7655            );
 7656            assert_eq!(
 7657                view.selections.display_ranges(cx),
 7658                &[
 7659                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7660                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7661                ]
 7662            );
 7663        });
 7664
 7665        view.update(cx, |view, cx| {
 7666            view.select_to_beginning_of_line(
 7667                &SelectToBeginningOfLine {
 7668                    stop_at_soft_wraps: true,
 7669                },
 7670                cx,
 7671            );
 7672            assert_eq!(
 7673                view.selections.display_ranges(cx),
 7674                &[
 7675                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7676                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7677                ]
 7678            );
 7679        });
 7680
 7681        view.update(cx, |view, cx| {
 7682            view.select_to_end_of_line(
 7683                &SelectToEndOfLine {
 7684                    stop_at_soft_wraps: true,
 7685                },
 7686                cx,
 7687            );
 7688            assert_eq!(
 7689                view.selections.display_ranges(cx),
 7690                &[
 7691                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7692                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7693                ]
 7694            );
 7695        });
 7696
 7697        view.update(cx, |view, cx| {
 7698            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7699            assert_eq!(view.display_text(cx), "ab\n  de");
 7700            assert_eq!(
 7701                view.selections.display_ranges(cx),
 7702                &[
 7703                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7704                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7705                ]
 7706            );
 7707        });
 7708
 7709        view.update(cx, |view, cx| {
 7710            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7711            assert_eq!(view.display_text(cx), "\n");
 7712            assert_eq!(
 7713                view.selections.display_ranges(cx),
 7714                &[
 7715                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7716                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7717                ]
 7718            );
 7719        });
 7720    }
 7721
 7722    #[gpui::test]
 7723    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7724        cx.set_global(Settings::test(cx));
 7725        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7726        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7727        view.update(cx, |view, cx| {
 7728            view.change_selections(None, cx, |s| {
 7729                s.select_display_ranges([
 7730                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7731                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7732                ])
 7733            });
 7734
 7735            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7736            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7737
 7738            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7739            assert_selection_ranges("use stdˇ::str::{foo, bar}\n\n  ˇ{baz.qux()}", view, cx);
 7740
 7741            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7742            assert_selection_ranges("use ˇstd::str::{foo, bar}\n\nˇ  {baz.qux()}", view, cx);
 7743
 7744            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7745            assert_selection_ranges("ˇuse std::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7746
 7747            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7748            assert_selection_ranges("ˇuse std::str::{foo, barˇ}\n\n  {baz.qux()}", view, cx);
 7749
 7750            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7751            assert_selection_ranges("useˇ std::str::{foo, bar}ˇ\n\n  {baz.qux()}", view, cx);
 7752
 7753            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7754            assert_selection_ranges("use stdˇ::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7755
 7756            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7757            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7758
 7759            view.move_right(&MoveRight, cx);
 7760            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7761            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7762
 7763            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7764            assert_selection_ranges("use std«ˇ::s»tr::{foo, bar}\n\n  «ˇ{b»az.qux()}", view, cx);
 7765
 7766            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7767            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7768        });
 7769    }
 7770
 7771    #[gpui::test]
 7772    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7773        cx.set_global(Settings::test(cx));
 7774        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7775        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7776
 7777        view.update(cx, |view, cx| {
 7778            view.set_wrap_width(Some(140.), cx);
 7779            assert_eq!(
 7780                view.display_text(cx),
 7781                "use one::{\n    two::three::\n    four::five\n};"
 7782            );
 7783
 7784            view.change_selections(None, cx, |s| {
 7785                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7786            });
 7787
 7788            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7789            assert_eq!(
 7790                view.selections.display_ranges(cx),
 7791                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7792            );
 7793
 7794            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7795            assert_eq!(
 7796                view.selections.display_ranges(cx),
 7797                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7798            );
 7799
 7800            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7801            assert_eq!(
 7802                view.selections.display_ranges(cx),
 7803                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7804            );
 7805
 7806            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7807            assert_eq!(
 7808                view.selections.display_ranges(cx),
 7809                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7810            );
 7811
 7812            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7813            assert_eq!(
 7814                view.selections.display_ranges(cx),
 7815                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7816            );
 7817
 7818            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7819            assert_eq!(
 7820                view.selections.display_ranges(cx),
 7821                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7822            );
 7823        });
 7824    }
 7825
 7826    #[gpui::test]
 7827    async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) {
 7828        let mut cx = EditorTestContext::new(cx).await;
 7829        cx.set_state("one «two threeˇ» four");
 7830        cx.update_editor(|editor, cx| {
 7831            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7832            assert_eq!(editor.text(cx), " four");
 7833        });
 7834    }
 7835
 7836    #[gpui::test]
 7837    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7838        cx.set_global(Settings::test(cx));
 7839        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7840        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7841
 7842        view.update(cx, |view, cx| {
 7843            view.change_selections(None, cx, |s| {
 7844                s.select_display_ranges([
 7845                    // an empty selection - the preceding word fragment is deleted
 7846                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7847                    // characters selected - they are deleted
 7848                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7849                ])
 7850            });
 7851            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7852        });
 7853
 7854        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7855
 7856        view.update(cx, |view, cx| {
 7857            view.change_selections(None, cx, |s| {
 7858                s.select_display_ranges([
 7859                    // an empty selection - the following word fragment is deleted
 7860                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7861                    // characters selected - they are deleted
 7862                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7863                ])
 7864            });
 7865            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7866        });
 7867
 7868        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7869    }
 7870
 7871    #[gpui::test]
 7872    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7873        cx.set_global(Settings::test(cx));
 7874        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7875        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7876
 7877        view.update(cx, |view, cx| {
 7878            view.change_selections(None, cx, |s| {
 7879                s.select_display_ranges([
 7880                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7881                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7882                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7883                ])
 7884            });
 7885
 7886            view.newline(&Newline, cx);
 7887            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7888        });
 7889    }
 7890
 7891    #[gpui::test]
 7892    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7893        cx.set_global(Settings::test(cx));
 7894        let buffer = MultiBuffer::build_simple(
 7895            "
 7896                a
 7897                b(
 7898                    X
 7899                )
 7900                c(
 7901                    X
 7902                )
 7903            "
 7904            .unindent()
 7905            .as_str(),
 7906            cx,
 7907        );
 7908
 7909        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7910            let mut editor = build_editor(buffer.clone(), cx);
 7911            editor.change_selections(None, cx, |s| {
 7912                s.select_ranges([
 7913                    Point::new(2, 4)..Point::new(2, 5),
 7914                    Point::new(5, 4)..Point::new(5, 5),
 7915                ])
 7916            });
 7917            editor
 7918        });
 7919
 7920        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7921        buffer.update(cx, |buffer, cx| {
 7922            buffer.edit(
 7923                [
 7924                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7925                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7926                ],
 7927                None,
 7928                cx,
 7929            );
 7930            assert_eq!(
 7931                buffer.read(cx).text(),
 7932                "
 7933                    a
 7934                    b()
 7935                    c()
 7936                "
 7937                .unindent()
 7938            );
 7939        });
 7940
 7941        editor.update(cx, |editor, cx| {
 7942            assert_eq!(
 7943                editor.selections.ranges(cx),
 7944                &[
 7945                    Point::new(1, 2)..Point::new(1, 2),
 7946                    Point::new(2, 2)..Point::new(2, 2),
 7947                ],
 7948            );
 7949
 7950            editor.newline(&Newline, cx);
 7951            assert_eq!(
 7952                editor.text(cx),
 7953                "
 7954                    a
 7955                    b(
 7956                    )
 7957                    c(
 7958                    )
 7959                "
 7960                .unindent()
 7961            );
 7962
 7963            // The selections are moved after the inserted newlines
 7964            assert_eq!(
 7965                editor.selections.ranges(cx),
 7966                &[
 7967                    Point::new(2, 0)..Point::new(2, 0),
 7968                    Point::new(4, 0)..Point::new(4, 0),
 7969                ],
 7970            );
 7971        });
 7972    }
 7973
 7974    #[gpui::test]
 7975    async fn test_newline_below(cx: &mut gpui::TestAppContext) {
 7976        let mut cx = EditorTestContext::new(cx).await;
 7977        cx.update(|cx| {
 7978            cx.update_global::<Settings, _, _>(|settings, _| {
 7979                settings.editor_overrides.tab_size = Some(NonZeroU32::new(4).unwrap());
 7980            });
 7981        });
 7982
 7983        let language = Arc::new(
 7984            Language::new(
 7985                LanguageConfig::default(),
 7986                Some(tree_sitter_rust::language()),
 7987            )
 7988            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 7989            .unwrap(),
 7990        );
 7991        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 7992
 7993        cx.set_state(indoc! {"
 7994            const a: ˇA = (
 7995 7996                    «const_functionˇ»(ˇ),
 7997                    so«mˇ»et«hˇ»ing_ˇelse,ˇ
 7998 7999            ˇ);ˇ
 8000        "});
 8001        cx.update_editor(|e, cx| e.newline_below(&NewlineBelow, cx));
 8002        cx.assert_editor_state(indoc! {"
 8003            const a: A = (
 8004                ˇ
 8005                (
 8006                    ˇ
 8007                    const_function(),
 8008                    ˇ
 8009                    ˇ
 8010                    something_else,
 8011                    ˇ
 8012                    ˇ
 8013                    ˇ
 8014                    ˇ
 8015                )
 8016                ˇ
 8017            );
 8018            ˇ
 8019            ˇ
 8020        "});
 8021    }
 8022
 8023    #[gpui::test]
 8024    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 8025        cx.set_global(Settings::test(cx));
 8026        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 8027        let (_, editor) = cx.add_window(Default::default(), |cx| {
 8028            let mut editor = build_editor(buffer.clone(), cx);
 8029            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 8030            editor
 8031        });
 8032
 8033        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 8034        buffer.update(cx, |buffer, cx| {
 8035            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
 8036            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 8037        });
 8038
 8039        editor.update(cx, |editor, cx| {
 8040            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 8041
 8042            editor.insert("Z", cx);
 8043            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 8044
 8045            // The selections are moved after the inserted characters
 8046            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 8047        });
 8048    }
 8049
 8050    #[gpui::test]
 8051    async fn test_tab(cx: &mut gpui::TestAppContext) {
 8052        let mut cx = EditorTestContext::new(cx).await;
 8053        cx.update(|cx| {
 8054            cx.update_global::<Settings, _, _>(|settings, _| {
 8055                settings.editor_overrides.tab_size = Some(NonZeroU32::new(3).unwrap());
 8056            });
 8057        });
 8058        cx.set_state(indoc! {"
 8059            ˇabˇc
 8060            ˇ🏀ˇ🏀ˇefg
 8061 8062        "});
 8063        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8064        cx.assert_editor_state(indoc! {"
 8065              ˇab ˇc
 8066              ˇ🏀  ˇ🏀  ˇefg
 8067           d  ˇ
 8068        "});
 8069
 8070        cx.set_state(indoc! {"
 8071            a
 8072            «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8073        "});
 8074        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8075        cx.assert_editor_state(indoc! {"
 8076            a
 8077               «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8078        "});
 8079    }
 8080
 8081    #[gpui::test]
 8082    async fn test_tab_on_blank_line_auto_indents(cx: &mut gpui::TestAppContext) {
 8083        let mut cx = EditorTestContext::new(cx).await;
 8084        let language = Arc::new(
 8085            Language::new(
 8086                LanguageConfig::default(),
 8087                Some(tree_sitter_rust::language()),
 8088            )
 8089            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 8090            .unwrap(),
 8091        );
 8092        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8093
 8094        // cursors that are already at the suggested indent level insert
 8095        // a soft tab. cursors that are to the left of the suggested indent
 8096        // auto-indent their line.
 8097        cx.set_state(indoc! {"
 8098            ˇ
 8099            const a: B = (
 8100                c(
 8101                    d(
 8102            ˇ
 8103                    )
 8104            ˇ
 8105            ˇ    )
 8106            );
 8107        "});
 8108        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8109        cx.assert_editor_state(indoc! {"
 8110                ˇ
 8111            const a: B = (
 8112                c(
 8113                    d(
 8114                        ˇ
 8115                    )
 8116                    ˇ
 8117                ˇ)
 8118            );
 8119        "});
 8120
 8121        // handle auto-indent when there are multiple cursors on the same line
 8122        cx.set_state(indoc! {"
 8123            const a: B = (
 8124                c(
 8125            ˇ    ˇ    
 8126            ˇ    )
 8127            );
 8128        "});
 8129        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8130        cx.assert_editor_state(indoc! {"
 8131            const a: B = (
 8132                c(
 8133                    ˇ
 8134                ˇ)
 8135            );
 8136        "});
 8137    }
 8138
 8139    #[gpui::test]
 8140    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 8141        let mut cx = EditorTestContext::new(cx).await;
 8142
 8143        cx.set_state(indoc! {"
 8144              «oneˇ» «twoˇ»
 8145            three
 8146             four
 8147        "});
 8148        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8149        cx.assert_editor_state(indoc! {"
 8150                «oneˇ» «twoˇ»
 8151            three
 8152             four
 8153        "});
 8154
 8155        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8156        cx.assert_editor_state(indoc! {"
 8157            «oneˇ» «twoˇ»
 8158            three
 8159             four
 8160        "});
 8161
 8162        // select across line ending
 8163        cx.set_state(indoc! {"
 8164            one two
 8165            t«hree
 8166            ˇ» four
 8167        "});
 8168        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8169        cx.assert_editor_state(indoc! {"
 8170            one two
 8171                t«hree
 8172            ˇ» four
 8173        "});
 8174
 8175        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8176        cx.assert_editor_state(indoc! {"
 8177            one two
 8178            t«hree
 8179            ˇ» four
 8180        "});
 8181
 8182        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8183        cx.set_state(indoc! {"
 8184            one two
 8185            ˇthree
 8186                four
 8187        "});
 8188        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8189        cx.assert_editor_state(indoc! {"
 8190            one two
 8191                ˇthree
 8192                four
 8193        "});
 8194
 8195        cx.set_state(indoc! {"
 8196            one two
 8197            ˇ    three
 8198             four
 8199        "});
 8200        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8201        cx.assert_editor_state(indoc! {"
 8202            one two
 8203            ˇthree
 8204             four
 8205        "});
 8206    }
 8207
 8208    #[gpui::test]
 8209    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 8210        let mut cx = EditorTestContext::new(cx).await;
 8211        cx.update(|cx| {
 8212            cx.update_global::<Settings, _, _>(|settings, _| {
 8213                settings.editor_overrides.hard_tabs = Some(true);
 8214            });
 8215        });
 8216
 8217        // select two ranges on one line
 8218        cx.set_state(indoc! {"
 8219            «oneˇ» «twoˇ»
 8220            three
 8221            four
 8222        "});
 8223        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8224        cx.assert_editor_state(indoc! {"
 8225            \t«oneˇ» «twoˇ»
 8226            three
 8227            four
 8228        "});
 8229        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8230        cx.assert_editor_state(indoc! {"
 8231            \t\t«oneˇ» «twoˇ»
 8232            three
 8233            four
 8234        "});
 8235        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8236        cx.assert_editor_state(indoc! {"
 8237            \t«oneˇ» «twoˇ»
 8238            three
 8239            four
 8240        "});
 8241        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8242        cx.assert_editor_state(indoc! {"
 8243            «oneˇ» «twoˇ»
 8244            three
 8245            four
 8246        "});
 8247
 8248        // select across a line ending
 8249        cx.set_state(indoc! {"
 8250            one two
 8251            t«hree
 8252            ˇ»four
 8253        "});
 8254        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8255        cx.assert_editor_state(indoc! {"
 8256            one two
 8257            \tt«hree
 8258            ˇ»four
 8259        "});
 8260        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8261        cx.assert_editor_state(indoc! {"
 8262            one two
 8263            \t\tt«hree
 8264            ˇ»four
 8265        "});
 8266        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8267        cx.assert_editor_state(indoc! {"
 8268            one two
 8269            \tt«hree
 8270            ˇ»four
 8271        "});
 8272        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8273        cx.assert_editor_state(indoc! {"
 8274            one two
 8275            t«hree
 8276            ˇ»four
 8277        "});
 8278
 8279        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8280        cx.set_state(indoc! {"
 8281            one two
 8282            ˇthree
 8283            four
 8284        "});
 8285        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8286        cx.assert_editor_state(indoc! {"
 8287            one two
 8288            ˇthree
 8289            four
 8290        "});
 8291        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8292        cx.assert_editor_state(indoc! {"
 8293            one two
 8294            \tˇthree
 8295            four
 8296        "});
 8297        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8298        cx.assert_editor_state(indoc! {"
 8299            one two
 8300            ˇthree
 8301            four
 8302        "});
 8303    }
 8304
 8305    #[gpui::test]
 8306    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 8307        cx.set_global(
 8308            Settings::test(cx)
 8309                .with_language_defaults(
 8310                    "TOML",
 8311                    EditorSettings {
 8312                        tab_size: Some(2.try_into().unwrap()),
 8313                        ..Default::default()
 8314                    },
 8315                )
 8316                .with_language_defaults(
 8317                    "Rust",
 8318                    EditorSettings {
 8319                        tab_size: Some(4.try_into().unwrap()),
 8320                        ..Default::default()
 8321                    },
 8322                ),
 8323        );
 8324        let toml_language = Arc::new(Language::new(
 8325            LanguageConfig {
 8326                name: "TOML".into(),
 8327                ..Default::default()
 8328            },
 8329            None,
 8330        ));
 8331        let rust_language = Arc::new(Language::new(
 8332            LanguageConfig {
 8333                name: "Rust".into(),
 8334                ..Default::default()
 8335            },
 8336            None,
 8337        ));
 8338
 8339        let toml_buffer = cx
 8340            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 8341        let rust_buffer = cx.add_model(|cx| {
 8342            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 8343        });
 8344        let multibuffer = cx.add_model(|cx| {
 8345            let mut multibuffer = MultiBuffer::new(0);
 8346            multibuffer.push_excerpts(
 8347                toml_buffer.clone(),
 8348                [ExcerptRange {
 8349                    context: Point::new(0, 0)..Point::new(2, 0),
 8350                    primary: None,
 8351                }],
 8352                cx,
 8353            );
 8354            multibuffer.push_excerpts(
 8355                rust_buffer.clone(),
 8356                [ExcerptRange {
 8357                    context: Point::new(0, 0)..Point::new(1, 0),
 8358                    primary: None,
 8359                }],
 8360                cx,
 8361            );
 8362            multibuffer
 8363        });
 8364
 8365        cx.add_window(Default::default(), |cx| {
 8366            let mut editor = build_editor(multibuffer, cx);
 8367
 8368            assert_eq!(
 8369                editor.text(cx),
 8370                indoc! {"
 8371                    a = 1
 8372                    b = 2
 8373
 8374                    const c: usize = 3;
 8375                "}
 8376            );
 8377
 8378            select_ranges(
 8379                &mut editor,
 8380                indoc! {"
 8381                    «aˇ» = 1
 8382                    b = 2
 8383
 8384                    «const c:ˇ» usize = 3;
 8385                "},
 8386                cx,
 8387            );
 8388
 8389            editor.tab(&Tab, cx);
 8390            assert_text_with_selections(
 8391                &mut editor,
 8392                indoc! {"
 8393                      «aˇ» = 1
 8394                    b = 2
 8395
 8396                        «const c:ˇ» usize = 3;
 8397                "},
 8398                cx,
 8399            );
 8400            editor.tab_prev(&TabPrev, cx);
 8401            assert_text_with_selections(
 8402                &mut editor,
 8403                indoc! {"
 8404                    «aˇ» = 1
 8405                    b = 2
 8406
 8407                    «const c:ˇ» usize = 3;
 8408                "},
 8409                cx,
 8410            );
 8411
 8412            editor
 8413        });
 8414    }
 8415
 8416    #[gpui::test]
 8417    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 8418        let mut cx = EditorTestContext::new(cx).await;
 8419
 8420        // Basic backspace
 8421        cx.set_state(indoc! {"
 8422            onˇe two three
 8423            fou«rˇ» five six
 8424            seven «ˇeight nine
 8425            »ten
 8426        "});
 8427        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8428        cx.assert_editor_state(indoc! {"
 8429            oˇe two three
 8430            fouˇ five six
 8431            seven ˇten
 8432        "});
 8433
 8434        // Test backspace inside and around indents
 8435        cx.set_state(indoc! {"
 8436            zero
 8437                ˇone
 8438                    ˇtwo
 8439                ˇ ˇ ˇ  three
 8440            ˇ  ˇ  four
 8441        "});
 8442        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8443        cx.assert_editor_state(indoc! {"
 8444            zero
 8445            ˇone
 8446                ˇtwo
 8447            ˇ  threeˇ  four
 8448        "});
 8449
 8450        // Test backspace with line_mode set to true
 8451        cx.update_editor(|e, _| e.selections.line_mode = true);
 8452        cx.set_state(indoc! {"
 8453            The ˇquick ˇbrown
 8454            fox jumps over
 8455            the lazy dog
 8456            ˇThe qu«ick bˇ»rown"});
 8457        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8458        cx.assert_editor_state(indoc! {"
 8459            ˇfox jumps over
 8460            the lazy dogˇ"});
 8461    }
 8462
 8463    #[gpui::test]
 8464    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8465        let mut cx = EditorTestContext::new(cx).await;
 8466
 8467        cx.set_state(indoc! {"
 8468            onˇe two three
 8469            fou«rˇ» five six
 8470            seven «ˇeight nine
 8471            »ten
 8472        "});
 8473        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8474        cx.assert_editor_state(indoc! {"
 8475            onˇ two three
 8476            fouˇ five six
 8477            seven ˇten
 8478        "});
 8479
 8480        // Test backspace with line_mode set to true
 8481        cx.update_editor(|e, _| e.selections.line_mode = true);
 8482        cx.set_state(indoc! {"
 8483            The ˇquick ˇbrown
 8484            fox «ˇjum»ps over
 8485            the lazy dog
 8486            ˇThe qu«ick bˇ»rown"});
 8487        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8488        cx.assert_editor_state("ˇthe lazy dogˇ");
 8489    }
 8490
 8491    #[gpui::test]
 8492    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8493        cx.set_global(Settings::test(cx));
 8494        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8495        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8496        view.update(cx, |view, cx| {
 8497            view.change_selections(None, cx, |s| {
 8498                s.select_display_ranges([
 8499                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8500                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8501                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8502                ])
 8503            });
 8504            view.delete_line(&DeleteLine, cx);
 8505            assert_eq!(view.display_text(cx), "ghi");
 8506            assert_eq!(
 8507                view.selections.display_ranges(cx),
 8508                vec![
 8509                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8510                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8511                ]
 8512            );
 8513        });
 8514
 8515        cx.set_global(Settings::test(cx));
 8516        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8517        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8518        view.update(cx, |view, cx| {
 8519            view.change_selections(None, cx, |s| {
 8520                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8521            });
 8522            view.delete_line(&DeleteLine, cx);
 8523            assert_eq!(view.display_text(cx), "ghi\n");
 8524            assert_eq!(
 8525                view.selections.display_ranges(cx),
 8526                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8527            );
 8528        });
 8529    }
 8530
 8531    #[gpui::test]
 8532    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8533        cx.set_global(Settings::test(cx));
 8534        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8535        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8536        view.update(cx, |view, cx| {
 8537            view.change_selections(None, cx, |s| {
 8538                s.select_display_ranges([
 8539                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8540                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8541                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8542                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8543                ])
 8544            });
 8545            view.duplicate_line(&DuplicateLine, cx);
 8546            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8547            assert_eq!(
 8548                view.selections.display_ranges(cx),
 8549                vec![
 8550                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8551                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8552                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8553                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8554                ]
 8555            );
 8556        });
 8557
 8558        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8559        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8560        view.update(cx, |view, cx| {
 8561            view.change_selections(None, cx, |s| {
 8562                s.select_display_ranges([
 8563                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8564                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8565                ])
 8566            });
 8567            view.duplicate_line(&DuplicateLine, cx);
 8568            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8569            assert_eq!(
 8570                view.selections.display_ranges(cx),
 8571                vec![
 8572                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8573                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8574                ]
 8575            );
 8576        });
 8577    }
 8578
 8579    #[gpui::test]
 8580    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8581        cx.set_global(Settings::test(cx));
 8582        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8583        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8584        view.update(cx, |view, cx| {
 8585            view.fold_ranges(
 8586                vec![
 8587                    Point::new(0, 2)..Point::new(1, 2),
 8588                    Point::new(2, 3)..Point::new(4, 1),
 8589                    Point::new(7, 0)..Point::new(8, 4),
 8590                ],
 8591                cx,
 8592            );
 8593            view.change_selections(None, cx, |s| {
 8594                s.select_display_ranges([
 8595                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8596                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8597                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8598                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8599                ])
 8600            });
 8601            assert_eq!(
 8602                view.display_text(cx),
 8603                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8604            );
 8605
 8606            view.move_line_up(&MoveLineUp, cx);
 8607            assert_eq!(
 8608                view.display_text(cx),
 8609                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8610            );
 8611            assert_eq!(
 8612                view.selections.display_ranges(cx),
 8613                vec![
 8614                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8615                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8616                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8617                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8618                ]
 8619            );
 8620        });
 8621
 8622        view.update(cx, |view, cx| {
 8623            view.move_line_down(&MoveLineDown, cx);
 8624            assert_eq!(
 8625                view.display_text(cx),
 8626                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8627            );
 8628            assert_eq!(
 8629                view.selections.display_ranges(cx),
 8630                vec![
 8631                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8632                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8633                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8634                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8635                ]
 8636            );
 8637        });
 8638
 8639        view.update(cx, |view, cx| {
 8640            view.move_line_down(&MoveLineDown, cx);
 8641            assert_eq!(
 8642                view.display_text(cx),
 8643                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8644            );
 8645            assert_eq!(
 8646                view.selections.display_ranges(cx),
 8647                vec![
 8648                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8649                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8650                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8651                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8652                ]
 8653            );
 8654        });
 8655
 8656        view.update(cx, |view, cx| {
 8657            view.move_line_up(&MoveLineUp, cx);
 8658            assert_eq!(
 8659                view.display_text(cx),
 8660                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8661            );
 8662            assert_eq!(
 8663                view.selections.display_ranges(cx),
 8664                vec![
 8665                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8666                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8667                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8668                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8669                ]
 8670            );
 8671        });
 8672    }
 8673
 8674    #[gpui::test]
 8675    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8676        cx.set_global(Settings::test(cx));
 8677        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8678        let snapshot = buffer.read(cx).snapshot(cx);
 8679        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8680        editor.update(cx, |editor, cx| {
 8681            editor.insert_blocks(
 8682                [BlockProperties {
 8683                    style: BlockStyle::Fixed,
 8684                    position: snapshot.anchor_after(Point::new(2, 0)),
 8685                    disposition: BlockDisposition::Below,
 8686                    height: 1,
 8687                    render: Arc::new(|_| Empty::new().boxed()),
 8688                }],
 8689                cx,
 8690            );
 8691            editor.change_selections(None, cx, |s| {
 8692                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8693            });
 8694            editor.move_line_down(&MoveLineDown, cx);
 8695        });
 8696    }
 8697
 8698    #[gpui::test]
 8699    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8700        cx.set_global(Settings::test(cx));
 8701
 8702        cx.add_window(Default::default(), |cx| {
 8703            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8704
 8705            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8706            editor.transpose(&Default::default(), cx);
 8707            assert_eq!(editor.text(cx), "bac");
 8708            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8709
 8710            editor.transpose(&Default::default(), cx);
 8711            assert_eq!(editor.text(cx), "bca");
 8712            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8713
 8714            editor.transpose(&Default::default(), cx);
 8715            assert_eq!(editor.text(cx), "bac");
 8716            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8717
 8718            editor
 8719        })
 8720        .1;
 8721
 8722        cx.add_window(Default::default(), |cx| {
 8723            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8724
 8725            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8726            editor.transpose(&Default::default(), cx);
 8727            assert_eq!(editor.text(cx), "acb\nde");
 8728            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8729
 8730            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8731            editor.transpose(&Default::default(), cx);
 8732            assert_eq!(editor.text(cx), "acbd\ne");
 8733            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8734
 8735            editor.transpose(&Default::default(), cx);
 8736            assert_eq!(editor.text(cx), "acbde\n");
 8737            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8738
 8739            editor.transpose(&Default::default(), cx);
 8740            assert_eq!(editor.text(cx), "acbd\ne");
 8741            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8742
 8743            editor
 8744        })
 8745        .1;
 8746
 8747        cx.add_window(Default::default(), |cx| {
 8748            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8749
 8750            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8751            editor.transpose(&Default::default(), cx);
 8752            assert_eq!(editor.text(cx), "bacd\ne");
 8753            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8754
 8755            editor.transpose(&Default::default(), cx);
 8756            assert_eq!(editor.text(cx), "bcade\n");
 8757            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8758
 8759            editor.transpose(&Default::default(), cx);
 8760            assert_eq!(editor.text(cx), "bcda\ne");
 8761            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8762
 8763            editor.transpose(&Default::default(), cx);
 8764            assert_eq!(editor.text(cx), "bcade\n");
 8765            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8766
 8767            editor.transpose(&Default::default(), cx);
 8768            assert_eq!(editor.text(cx), "bcaed\n");
 8769            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8770
 8771            editor
 8772        })
 8773        .1;
 8774
 8775        cx.add_window(Default::default(), |cx| {
 8776            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8777
 8778            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8779            editor.transpose(&Default::default(), cx);
 8780            assert_eq!(editor.text(cx), "🏀🍐✋");
 8781            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8782
 8783            editor.transpose(&Default::default(), cx);
 8784            assert_eq!(editor.text(cx), "🏀✋🍐");
 8785            assert_eq!(editor.selections.ranges(cx), [11..11]);
 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
 8792        })
 8793        .1;
 8794    }
 8795
 8796    #[gpui::test]
 8797    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8798        let mut cx = EditorTestContext::new(cx).await;
 8799
 8800        cx.set_state("«one✅ ˇ»two «three ˇ»four «five ˇ»six ");
 8801        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8802        cx.assert_editor_state("ˇtwo ˇfour ˇsix ");
 8803
 8804        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8805        cx.set_state("two ˇfour ˇsix ˇ");
 8806        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8807        cx.assert_editor_state("two one✅ ˇfour three ˇsix five ˇ");
 8808
 8809        // Paste again but with only two cursors. Since the number of cursors doesn't
 8810        // match the number of slices in the clipboard, the entire clipboard text
 8811        // is pasted at each cursor.
 8812        cx.set_state("ˇtwo one✅ four three six five ˇ");
 8813        cx.update_editor(|e, cx| {
 8814            e.handle_input("( ", cx);
 8815            e.paste(&Paste, cx);
 8816            e.handle_input(") ", cx);
 8817        });
 8818        cx.assert_editor_state(indoc! {"
 8819            ( one✅ 
 8820            three 
 8821            five ) ˇtwo one✅ four three six five ( one✅ 
 8822            three 
 8823            five ) ˇ"});
 8824
 8825        // Cut with three selections, one of which is full-line.
 8826        cx.set_state(indoc! {"
 8827            1«2ˇ»3
 8828            4ˇ567
 8829            «8ˇ»9"});
 8830        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8831        cx.assert_editor_state(indoc! {"
 8832            1ˇ3
 8833            ˇ9"});
 8834
 8835        // Paste with three selections, noticing how the copied selection that was full-line
 8836        // gets inserted before the second cursor.
 8837        cx.set_state(indoc! {"
 8838            1ˇ3
 8839 8840            «oˇ»ne"});
 8841        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8842        cx.assert_editor_state(indoc! {"
 8843            12ˇ3
 8844            4567
 8845 8846            8ˇne"});
 8847
 8848        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8849        cx.set_state(indoc! {"
 8850            The quick brown
 8851            fox juˇmps over
 8852            the lazy dog"});
 8853        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8854        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8855
 8856        // Paste with three selections, noticing how the copied full-line selection is inserted
 8857        // before the empty selections but replaces the selection that is non-empty.
 8858        cx.set_state(indoc! {"
 8859            Tˇhe quick brown
 8860            «foˇ»x jumps over
 8861            tˇhe lazy dog"});
 8862        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8863        cx.assert_editor_state(indoc! {"
 8864            fox jumps over
 8865            Tˇhe quick brown
 8866            fox jumps over
 8867            ˇx jumps over
 8868            fox jumps over
 8869            tˇhe lazy dog"});
 8870    }
 8871
 8872    #[gpui::test]
 8873    async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
 8874        let mut cx = EditorTestContext::new(cx).await;
 8875        let language = Arc::new(Language::new(
 8876            LanguageConfig::default(),
 8877            Some(tree_sitter_rust::language()),
 8878        ));
 8879        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8880
 8881        // Cut an indented block, without the leading whitespace.
 8882        cx.set_state(indoc! {"
 8883            const a: B = (
 8884                c(),
 8885                «d(
 8886                    e,
 8887                    f
 8888                )ˇ»
 8889            );
 8890        "});
 8891        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8892        cx.assert_editor_state(indoc! {"
 8893            const a: B = (
 8894                c(),
 8895                ˇ
 8896            );
 8897        "});
 8898
 8899        // Paste it at the same position.
 8900        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8901        cx.assert_editor_state(indoc! {"
 8902            const a: B = (
 8903                c(),
 8904                d(
 8905                    e,
 8906                    f
 8907 8908            );
 8909        "});
 8910
 8911        // Paste it at a line with a lower indent level.
 8912        cx.set_state(indoc! {"
 8913            ˇ
 8914            const a: B = (
 8915                c(),
 8916            );
 8917        "});
 8918        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8919        cx.assert_editor_state(indoc! {"
 8920            d(
 8921                e,
 8922                f
 8923 8924            const a: B = (
 8925                c(),
 8926            );
 8927        "});
 8928
 8929        // Cut an indented block, with the leading whitespace.
 8930        cx.set_state(indoc! {"
 8931            const a: B = (
 8932                c(),
 8933            «    d(
 8934                    e,
 8935                    f
 8936                )
 8937            ˇ»);
 8938        "});
 8939        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8940        cx.assert_editor_state(indoc! {"
 8941            const a: B = (
 8942                c(),
 8943            ˇ);
 8944        "});
 8945
 8946        // Paste it at the same position.
 8947        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8948        cx.assert_editor_state(indoc! {"
 8949            const a: B = (
 8950                c(),
 8951                d(
 8952                    e,
 8953                    f
 8954                )
 8955            ˇ);
 8956        "});
 8957
 8958        // Paste it at a line with a higher indent level.
 8959        cx.set_state(indoc! {"
 8960            const a: B = (
 8961                c(),
 8962                d(
 8963                    e,
 8964 8965                )
 8966            );
 8967        "});
 8968        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8969        cx.assert_editor_state(indoc! {"
 8970            const a: B = (
 8971                c(),
 8972                d(
 8973                    e,
 8974                    f    d(
 8975                        e,
 8976                        f
 8977                    )
 8978            ˇ
 8979                )
 8980            );
 8981        "});
 8982    }
 8983
 8984    #[gpui::test]
 8985    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8986        cx.set_global(Settings::test(cx));
 8987        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8988        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8989        view.update(cx, |view, cx| {
 8990            view.select_all(&SelectAll, cx);
 8991            assert_eq!(
 8992                view.selections.display_ranges(cx),
 8993                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8994            );
 8995        });
 8996    }
 8997
 8998    #[gpui::test]
 8999    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 9000        cx.set_global(Settings::test(cx));
 9001        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 9002        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9003        view.update(cx, |view, cx| {
 9004            view.change_selections(None, cx, |s| {
 9005                s.select_display_ranges([
 9006                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9007                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9008                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9009                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 9010                ])
 9011            });
 9012            view.select_line(&SelectLine, cx);
 9013            assert_eq!(
 9014                view.selections.display_ranges(cx),
 9015                vec![
 9016                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 9017                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 9018                ]
 9019            );
 9020        });
 9021
 9022        view.update(cx, |view, cx| {
 9023            view.select_line(&SelectLine, cx);
 9024            assert_eq!(
 9025                view.selections.display_ranges(cx),
 9026                vec![
 9027                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 9028                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 9029                ]
 9030            );
 9031        });
 9032
 9033        view.update(cx, |view, cx| {
 9034            view.select_line(&SelectLine, cx);
 9035            assert_eq!(
 9036                view.selections.display_ranges(cx),
 9037                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 9038            );
 9039        });
 9040    }
 9041
 9042    #[gpui::test]
 9043    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 9044        cx.set_global(Settings::test(cx));
 9045        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 9046        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9047        view.update(cx, |view, cx| {
 9048            view.fold_ranges(
 9049                vec![
 9050                    Point::new(0, 2)..Point::new(1, 2),
 9051                    Point::new(2, 3)..Point::new(4, 1),
 9052                    Point::new(7, 0)..Point::new(8, 4),
 9053                ],
 9054                cx,
 9055            );
 9056            view.change_selections(None, cx, |s| {
 9057                s.select_display_ranges([
 9058                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9059                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9060                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9061                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9062                ])
 9063            });
 9064            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 9065        });
 9066
 9067        view.update(cx, |view, cx| {
 9068            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9069            assert_eq!(
 9070                view.display_text(cx),
 9071                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 9072            );
 9073            assert_eq!(
 9074                view.selections.display_ranges(cx),
 9075                [
 9076                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 9077                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9078                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 9079                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 9080                ]
 9081            );
 9082        });
 9083
 9084        view.update(cx, |view, cx| {
 9085            view.change_selections(None, cx, |s| {
 9086                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 9087            });
 9088            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9089            assert_eq!(
 9090                view.display_text(cx),
 9091                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 9092            );
 9093            assert_eq!(
 9094                view.selections.display_ranges(cx),
 9095                [
 9096                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 9097                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 9098                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9099                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 9100                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 9101                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 9102                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 9103                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 9104                ]
 9105            );
 9106        });
 9107    }
 9108
 9109    #[gpui::test]
 9110    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 9111        cx.set_global(Settings::test(cx));
 9112        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 9113        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9114
 9115        view.update(cx, |view, cx| {
 9116            view.change_selections(None, cx, |s| {
 9117                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 9118            });
 9119        });
 9120        view.update(cx, |view, cx| {
 9121            view.add_selection_above(&AddSelectionAbove, cx);
 9122            assert_eq!(
 9123                view.selections.display_ranges(cx),
 9124                vec![
 9125                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9126                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9127                ]
 9128            );
 9129        });
 9130
 9131        view.update(cx, |view, cx| {
 9132            view.add_selection_above(&AddSelectionAbove, cx);
 9133            assert_eq!(
 9134                view.selections.display_ranges(cx),
 9135                vec![
 9136                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9137                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9138                ]
 9139            );
 9140        });
 9141
 9142        view.update(cx, |view, cx| {
 9143            view.add_selection_below(&AddSelectionBelow, cx);
 9144            assert_eq!(
 9145                view.selections.display_ranges(cx),
 9146                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9147            );
 9148
 9149            view.undo_selection(&UndoSelection, cx);
 9150            assert_eq!(
 9151                view.selections.display_ranges(cx),
 9152                vec![
 9153                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9154                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9155                ]
 9156            );
 9157
 9158            view.redo_selection(&RedoSelection, cx);
 9159            assert_eq!(
 9160                view.selections.display_ranges(cx),
 9161                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9162            );
 9163        });
 9164
 9165        view.update(cx, |view, cx| {
 9166            view.add_selection_below(&AddSelectionBelow, cx);
 9167            assert_eq!(
 9168                view.selections.display_ranges(cx),
 9169                vec![
 9170                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9171                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9172                ]
 9173            );
 9174        });
 9175
 9176        view.update(cx, |view, cx| {
 9177            view.add_selection_below(&AddSelectionBelow, cx);
 9178            assert_eq!(
 9179                view.selections.display_ranges(cx),
 9180                vec![
 9181                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9182                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9183                ]
 9184            );
 9185        });
 9186
 9187        view.update(cx, |view, cx| {
 9188            view.change_selections(None, cx, |s| {
 9189                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 9190            });
 9191        });
 9192        view.update(cx, |view, cx| {
 9193            view.add_selection_below(&AddSelectionBelow, cx);
 9194            assert_eq!(
 9195                view.selections.display_ranges(cx),
 9196                vec![
 9197                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9198                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9199                ]
 9200            );
 9201        });
 9202
 9203        view.update(cx, |view, cx| {
 9204            view.add_selection_below(&AddSelectionBelow, cx);
 9205            assert_eq!(
 9206                view.selections.display_ranges(cx),
 9207                vec![
 9208                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9209                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9210                ]
 9211            );
 9212        });
 9213
 9214        view.update(cx, |view, cx| {
 9215            view.add_selection_above(&AddSelectionAbove, cx);
 9216            assert_eq!(
 9217                view.selections.display_ranges(cx),
 9218                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9219            );
 9220        });
 9221
 9222        view.update(cx, |view, cx| {
 9223            view.add_selection_above(&AddSelectionAbove, cx);
 9224            assert_eq!(
 9225                view.selections.display_ranges(cx),
 9226                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9227            );
 9228        });
 9229
 9230        view.update(cx, |view, cx| {
 9231            view.change_selections(None, cx, |s| {
 9232                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 9233            });
 9234            view.add_selection_below(&AddSelectionBelow, cx);
 9235            assert_eq!(
 9236                view.selections.display_ranges(cx),
 9237                vec![
 9238                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9239                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9240                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9241                ]
 9242            );
 9243        });
 9244
 9245        view.update(cx, |view, cx| {
 9246            view.add_selection_below(&AddSelectionBelow, cx);
 9247            assert_eq!(
 9248                view.selections.display_ranges(cx),
 9249                vec![
 9250                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9251                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9252                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9253                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 9254                ]
 9255            );
 9256        });
 9257
 9258        view.update(cx, |view, cx| {
 9259            view.add_selection_above(&AddSelectionAbove, cx);
 9260            assert_eq!(
 9261                view.selections.display_ranges(cx),
 9262                vec![
 9263                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9264                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9265                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9266                ]
 9267            );
 9268        });
 9269
 9270        view.update(cx, |view, cx| {
 9271            view.change_selections(None, cx, |s| {
 9272                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 9273            });
 9274        });
 9275        view.update(cx, |view, cx| {
 9276            view.add_selection_above(&AddSelectionAbove, cx);
 9277            assert_eq!(
 9278                view.selections.display_ranges(cx),
 9279                vec![
 9280                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 9281                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9282                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9283                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9284                ]
 9285            );
 9286        });
 9287
 9288        view.update(cx, |view, cx| {
 9289            view.add_selection_below(&AddSelectionBelow, cx);
 9290            assert_eq!(
 9291                view.selections.display_ranges(cx),
 9292                vec![
 9293                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9294                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9295                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9296                ]
 9297            );
 9298        });
 9299    }
 9300
 9301    #[gpui::test]
 9302    async fn test_select_next(cx: &mut gpui::TestAppContext) {
 9303        let mut cx = EditorTestContext::new(cx).await;
 9304        cx.set_state("abc\nˇabc abc\ndefabc\nabc");
 9305
 9306        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9307        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9308
 9309        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9310        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9311
 9312        cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx));
 9313        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9314
 9315        cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx));
 9316        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9317
 9318        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9319        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9320
 9321        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9322        cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9323    }
 9324
 9325    #[gpui::test]
 9326    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 9327        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9328        let language = Arc::new(Language::new(
 9329            LanguageConfig::default(),
 9330            Some(tree_sitter_rust::language()),
 9331        ));
 9332
 9333        let text = r#"
 9334            use mod1::mod2::{mod3, mod4};
 9335
 9336            fn fn_1(param1: bool, param2: &str) {
 9337                let var1 = "text";
 9338            }
 9339        "#
 9340        .unindent();
 9341
 9342        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9343        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9344        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9345        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9346            .await;
 9347
 9348        view.update(cx, |view, cx| {
 9349            view.change_selections(None, cx, |s| {
 9350                s.select_display_ranges([
 9351                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9352                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9353                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9354                ]);
 9355            });
 9356            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9357        });
 9358        assert_eq!(
 9359            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 9360            &[
 9361                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9362                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9363                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9364            ]
 9365        );
 9366
 9367        view.update(cx, |view, cx| {
 9368            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9369        });
 9370        assert_eq!(
 9371            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9372            &[
 9373                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9374                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9375            ]
 9376        );
 9377
 9378        view.update(cx, |view, cx| {
 9379            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9380        });
 9381        assert_eq!(
 9382            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9383            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9384        );
 9385
 9386        // Trying to expand the selected syntax node one more time has no effect.
 9387        view.update(cx, |view, cx| {
 9388            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9389        });
 9390        assert_eq!(
 9391            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9392            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9393        );
 9394
 9395        view.update(cx, |view, cx| {
 9396            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9397        });
 9398        assert_eq!(
 9399            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9400            &[
 9401                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9402                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9403            ]
 9404        );
 9405
 9406        view.update(cx, |view, cx| {
 9407            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9408        });
 9409        assert_eq!(
 9410            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9411            &[
 9412                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9413                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9414                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9415            ]
 9416        );
 9417
 9418        view.update(cx, |view, cx| {
 9419            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9420        });
 9421        assert_eq!(
 9422            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9423            &[
 9424                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9425                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9426                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9427            ]
 9428        );
 9429
 9430        // Trying to shrink the selected syntax node one more time has no effect.
 9431        view.update(cx, |view, cx| {
 9432            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9433        });
 9434        assert_eq!(
 9435            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9436            &[
 9437                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9438                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9439                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9440            ]
 9441        );
 9442
 9443        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9444        // a fold.
 9445        view.update(cx, |view, cx| {
 9446            view.fold_ranges(
 9447                vec![
 9448                    Point::new(0, 21)..Point::new(0, 24),
 9449                    Point::new(3, 20)..Point::new(3, 22),
 9450                ],
 9451                cx,
 9452            );
 9453            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9454        });
 9455        assert_eq!(
 9456            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9457            &[
 9458                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9459                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9460                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9461            ]
 9462        );
 9463    }
 9464
 9465    #[gpui::test]
 9466    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9467        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9468        let language = Arc::new(
 9469            Language::new(
 9470                LanguageConfig {
 9471                    brackets: vec![
 9472                        BracketPair {
 9473                            start: "{".to_string(),
 9474                            end: "}".to_string(),
 9475                            close: false,
 9476                            newline: true,
 9477                        },
 9478                        BracketPair {
 9479                            start: "(".to_string(),
 9480                            end: ")".to_string(),
 9481                            close: false,
 9482                            newline: true,
 9483                        },
 9484                    ],
 9485                    ..Default::default()
 9486                },
 9487                Some(tree_sitter_rust::language()),
 9488            )
 9489            .with_indents_query(
 9490                r#"
 9491                (_ "(" ")" @end) @indent
 9492                (_ "{" "}" @end) @indent
 9493                "#,
 9494            )
 9495            .unwrap(),
 9496        );
 9497
 9498        let text = "fn a() {}";
 9499
 9500        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9501        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9502        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9503        editor
 9504            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9505            .await;
 9506
 9507        editor.update(cx, |editor, cx| {
 9508            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 9509            editor.newline(&Newline, cx);
 9510            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9511            assert_eq!(
 9512                editor.selections.ranges(cx),
 9513                &[
 9514                    Point::new(1, 4)..Point::new(1, 4),
 9515                    Point::new(3, 4)..Point::new(3, 4),
 9516                    Point::new(5, 0)..Point::new(5, 0)
 9517                ]
 9518            );
 9519        });
 9520    }
 9521
 9522    #[gpui::test]
 9523    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9524        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9525        let language = Arc::new(Language::new(
 9526            LanguageConfig {
 9527                brackets: vec![
 9528                    BracketPair {
 9529                        start: "{".to_string(),
 9530                        end: "}".to_string(),
 9531                        close: true,
 9532                        newline: true,
 9533                    },
 9534                    BracketPair {
 9535                        start: "/*".to_string(),
 9536                        end: " */".to_string(),
 9537                        close: true,
 9538                        newline: true,
 9539                    },
 9540                    BracketPair {
 9541                        start: "[".to_string(),
 9542                        end: "]".to_string(),
 9543                        close: false,
 9544                        newline: true,
 9545                    },
 9546                ],
 9547                autoclose_before: "})]".to_string(),
 9548                ..Default::default()
 9549            },
 9550            Some(tree_sitter_rust::language()),
 9551        ));
 9552
 9553        let text = r#"
 9554            a
 9555
 9556            /
 9557
 9558        "#
 9559        .unindent();
 9560
 9561        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9562        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9563        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9564        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9565            .await;
 9566
 9567        view.update(cx, |view, cx| {
 9568            view.change_selections(None, cx, |s| {
 9569                s.select_display_ranges([
 9570                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9571                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9572                ])
 9573            });
 9574
 9575            view.handle_input("{", cx);
 9576            view.handle_input("{", cx);
 9577            view.handle_input("{", cx);
 9578            assert_eq!(
 9579                view.text(cx),
 9580                "
 9581                {{{}}}
 9582                {{{}}}
 9583                /
 9584
 9585                "
 9586                .unindent()
 9587            );
 9588
 9589            view.move_right(&MoveRight, cx);
 9590            view.handle_input("}", cx);
 9591            view.handle_input("}", cx);
 9592            view.handle_input("}", cx);
 9593            assert_eq!(
 9594                view.text(cx),
 9595                "
 9596                {{{}}}}
 9597                {{{}}}}
 9598                /
 9599
 9600                "
 9601                .unindent()
 9602            );
 9603
 9604            view.undo(&Undo, cx);
 9605            view.handle_input("/", cx);
 9606            view.handle_input("*", cx);
 9607            assert_eq!(
 9608                view.text(cx),
 9609                "
 9610                /* */
 9611                /* */
 9612                /
 9613
 9614                "
 9615                .unindent()
 9616            );
 9617
 9618            view.undo(&Undo, cx);
 9619            view.change_selections(None, cx, |s| {
 9620                s.select_display_ranges([
 9621                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9622                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9623                ])
 9624            });
 9625            view.handle_input("*", cx);
 9626            assert_eq!(
 9627                view.text(cx),
 9628                "
 9629                a
 9630
 9631                /*
 9632                *
 9633                "
 9634                .unindent()
 9635            );
 9636
 9637            // Don't autoclose if the next character isn't whitespace and isn't
 9638            // listed in the language's "autoclose_before" section.
 9639            view.finalize_last_transaction(cx);
 9640            view.change_selections(None, cx, |s| {
 9641                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 9642            });
 9643            view.handle_input("{", cx);
 9644            assert_eq!(
 9645                view.text(cx),
 9646                "
 9647                {a
 9648
 9649                /*
 9650                *
 9651                "
 9652                .unindent()
 9653            );
 9654
 9655            view.undo(&Undo, cx);
 9656            view.change_selections(None, cx, |s| {
 9657                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 9658            });
 9659            view.handle_input("{", cx);
 9660            assert_eq!(
 9661                view.text(cx),
 9662                "
 9663                {a}
 9664
 9665                /*
 9666                *
 9667                "
 9668                .unindent()
 9669            );
 9670            assert_eq!(
 9671                view.selections.display_ranges(cx),
 9672                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9673            );
 9674
 9675            view.undo(&Undo, cx);
 9676            view.handle_input("[", cx);
 9677            assert_eq!(
 9678                view.text(cx),
 9679                "
 9680                [a]
 9681                
 9682                /*
 9683                *
 9684                "
 9685                .unindent()
 9686            );
 9687            assert_eq!(
 9688                view.selections.display_ranges(cx),
 9689                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9690            );
 9691
 9692            view.undo(&Undo, cx);
 9693            view.change_selections(None, cx, |s| {
 9694                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9695            });
 9696            view.handle_input("[", cx);
 9697            assert_eq!(
 9698                view.text(cx),
 9699                "
 9700                a[
 9701                
 9702                /*
 9703                *
 9704                "
 9705                .unindent()
 9706            );
 9707            assert_eq!(
 9708                view.selections.display_ranges(cx),
 9709                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9710            );
 9711        });
 9712    }
 9713
 9714    #[gpui::test]
 9715    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9716        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9717        let language = Arc::new(Language::new(
 9718            LanguageConfig {
 9719                brackets: vec![BracketPair {
 9720                    start: "{".to_string(),
 9721                    end: "}".to_string(),
 9722                    close: true,
 9723                    newline: true,
 9724                }],
 9725                ..Default::default()
 9726            },
 9727            Some(tree_sitter_rust::language()),
 9728        ));
 9729
 9730        let text = r#"
 9731            a
 9732            b
 9733            c
 9734        "#
 9735        .unindent();
 9736
 9737        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9738        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9739        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9740        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9741            .await;
 9742
 9743        view.update(cx, |view, cx| {
 9744            view.change_selections(None, cx, |s| {
 9745                s.select_display_ranges([
 9746                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9747                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9748                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9749                ])
 9750            });
 9751
 9752            view.handle_input("{", cx);
 9753            view.handle_input("{", cx);
 9754            view.handle_input("{", cx);
 9755            assert_eq!(
 9756                view.text(cx),
 9757                "
 9758                {{{a}}}
 9759                {{{b}}}
 9760                {{{c}}}
 9761                "
 9762                .unindent()
 9763            );
 9764            assert_eq!(
 9765                view.selections.display_ranges(cx),
 9766                [
 9767                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9768                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9769                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9770                ]
 9771            );
 9772
 9773            view.undo(&Undo, cx);
 9774            assert_eq!(
 9775                view.text(cx),
 9776                "
 9777                a
 9778                b
 9779                c
 9780                "
 9781                .unindent()
 9782            );
 9783            assert_eq!(
 9784                view.selections.display_ranges(cx),
 9785                [
 9786                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9787                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9788                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9789                ]
 9790            );
 9791        });
 9792    }
 9793
 9794    #[gpui::test]
 9795    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9796        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9797        let language = Arc::new(Language::new(
 9798            LanguageConfig {
 9799                brackets: vec![BracketPair {
 9800                    start: "{".to_string(),
 9801                    end: "}".to_string(),
 9802                    close: true,
 9803                    newline: true,
 9804                }],
 9805                autoclose_before: "}".to_string(),
 9806                ..Default::default()
 9807            },
 9808            Some(tree_sitter_rust::language()),
 9809        ));
 9810
 9811        let text = r#"
 9812            a
 9813            b
 9814            c
 9815        "#
 9816        .unindent();
 9817
 9818        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9819        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9820        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9821        editor
 9822            .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9823            .await;
 9824
 9825        editor.update(cx, |editor, cx| {
 9826            editor.change_selections(None, cx, |s| {
 9827                s.select_ranges([
 9828                    Point::new(0, 1)..Point::new(0, 1),
 9829                    Point::new(1, 1)..Point::new(1, 1),
 9830                    Point::new(2, 1)..Point::new(2, 1),
 9831                ])
 9832            });
 9833
 9834            editor.handle_input("{", cx);
 9835            editor.handle_input("{", cx);
 9836            editor.handle_input("_", cx);
 9837            assert_eq!(
 9838                editor.text(cx),
 9839                "
 9840                a{{_}}
 9841                b{{_}}
 9842                c{{_}}
 9843                "
 9844                .unindent()
 9845            );
 9846            assert_eq!(
 9847                editor.selections.ranges::<Point>(cx),
 9848                [
 9849                    Point::new(0, 4)..Point::new(0, 4),
 9850                    Point::new(1, 4)..Point::new(1, 4),
 9851                    Point::new(2, 4)..Point::new(2, 4)
 9852                ]
 9853            );
 9854
 9855            editor.backspace(&Default::default(), cx);
 9856            editor.backspace(&Default::default(), cx);
 9857            assert_eq!(
 9858                editor.text(cx),
 9859                "
 9860                a{}
 9861                b{}
 9862                c{}
 9863                "
 9864                .unindent()
 9865            );
 9866            assert_eq!(
 9867                editor.selections.ranges::<Point>(cx),
 9868                [
 9869                    Point::new(0, 2)..Point::new(0, 2),
 9870                    Point::new(1, 2)..Point::new(1, 2),
 9871                    Point::new(2, 2)..Point::new(2, 2)
 9872                ]
 9873            );
 9874
 9875            editor.delete_to_previous_word_start(&Default::default(), cx);
 9876            assert_eq!(
 9877                editor.text(cx),
 9878                "
 9879                a
 9880                b
 9881                c
 9882                "
 9883                .unindent()
 9884            );
 9885            assert_eq!(
 9886                editor.selections.ranges::<Point>(cx),
 9887                [
 9888                    Point::new(0, 1)..Point::new(0, 1),
 9889                    Point::new(1, 1)..Point::new(1, 1),
 9890                    Point::new(2, 1)..Point::new(2, 1)
 9891                ]
 9892            );
 9893        });
 9894    }
 9895
 9896    #[gpui::test]
 9897    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9898        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9899
 9900        let (text, insertion_ranges) = marked_text_ranges(
 9901            indoc! {"
 9902                a.ˇ b
 9903                a.ˇ b
 9904                a.ˇ b
 9905            "},
 9906            false,
 9907        );
 9908
 9909        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9910        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9911
 9912        editor.update(cx, |editor, cx| {
 9913            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9914
 9915            editor
 9916                .insert_snippet(&insertion_ranges, snippet, cx)
 9917                .unwrap();
 9918
 9919            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text: &str) {
 9920                let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
 9921                assert_eq!(editor.text(cx), expected_text);
 9922                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9923            }
 9924
 9925            assert(
 9926                editor,
 9927                cx,
 9928                indoc! {"
 9929                    a.f(«one», two, «three») b
 9930                    a.f(«one», two, «three») b
 9931                    a.f(«one», two, «three») b
 9932                "},
 9933            );
 9934
 9935            // Can't move earlier than the first tab stop
 9936            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9937            assert(
 9938                editor,
 9939                cx,
 9940                indoc! {"
 9941                    a.f(«one», two, «three») b
 9942                    a.f(«one», two, «three») b
 9943                    a.f(«one», two, «three») b
 9944                "},
 9945            );
 9946
 9947            assert!(editor.move_to_next_snippet_tabstop(cx));
 9948            assert(
 9949                editor,
 9950                cx,
 9951                indoc! {"
 9952                    a.f(one, «two», three) b
 9953                    a.f(one, «two», three) b
 9954                    a.f(one, «two», three) b
 9955                "},
 9956            );
 9957
 9958            editor.move_to_prev_snippet_tabstop(cx);
 9959            assert(
 9960                editor,
 9961                cx,
 9962                indoc! {"
 9963                    a.f(«one», two, «three») b
 9964                    a.f(«one», two, «three») b
 9965                    a.f(«one», two, «three») b
 9966                "},
 9967            );
 9968
 9969            assert!(editor.move_to_next_snippet_tabstop(cx));
 9970            assert(
 9971                editor,
 9972                cx,
 9973                indoc! {"
 9974                    a.f(one, «two», three) b
 9975                    a.f(one, «two», three) b
 9976                    a.f(one, «two», three) b
 9977                "},
 9978            );
 9979            assert!(editor.move_to_next_snippet_tabstop(cx));
 9980            assert(
 9981                editor,
 9982                cx,
 9983                indoc! {"
 9984                    a.f(one, two, three)ˇ b
 9985                    a.f(one, two, three)ˇ b
 9986                    a.f(one, two, three)ˇ b
 9987                "},
 9988            );
 9989
 9990            // As soon as the last tab stop is reached, snippet state is gone
 9991            editor.move_to_prev_snippet_tabstop(cx);
 9992            assert(
 9993                editor,
 9994                cx,
 9995                indoc! {"
 9996                    a.f(one, two, three)ˇ b
 9997                    a.f(one, two, three)ˇ b
 9998                    a.f(one, two, three)ˇ b
 9999                "},
10000            );
10001        });
10002    }
10003
10004    #[gpui::test]
10005    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
10006        cx.foreground().forbid_parking();
10007
10008        let mut language = Language::new(
10009            LanguageConfig {
10010                name: "Rust".into(),
10011                path_suffixes: vec!["rs".to_string()],
10012                ..Default::default()
10013            },
10014            Some(tree_sitter_rust::language()),
10015        );
10016        let mut fake_servers = language
10017            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10018                capabilities: lsp::ServerCapabilities {
10019                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
10020                    ..Default::default()
10021                },
10022                ..Default::default()
10023            }))
10024            .await;
10025
10026        let fs = FakeFs::new(cx.background().clone());
10027        fs.insert_file("/file.rs", Default::default()).await;
10028
10029        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10030        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10031        let buffer = project
10032            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10033            .await
10034            .unwrap();
10035
10036        cx.foreground().start_waiting();
10037        let fake_server = fake_servers.next().await.unwrap();
10038
10039        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10040        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10041        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10042        assert!(cx.read(|cx| editor.is_dirty(cx)));
10043
10044        let save = cx.update(|cx| editor.save(project.clone(), cx));
10045        fake_server
10046            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10047                assert_eq!(
10048                    params.text_document.uri,
10049                    lsp::Url::from_file_path("/file.rs").unwrap()
10050                );
10051                assert_eq!(params.options.tab_size, 4);
10052                Ok(Some(vec![lsp::TextEdit::new(
10053                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10054                    ", ".to_string(),
10055                )]))
10056            })
10057            .next()
10058            .await;
10059        cx.foreground().start_waiting();
10060        save.await.unwrap();
10061        assert_eq!(
10062            editor.read_with(cx, |editor, cx| editor.text(cx)),
10063            "one, two\nthree\n"
10064        );
10065        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10066
10067        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10068        assert!(cx.read(|cx| editor.is_dirty(cx)));
10069
10070        // Ensure we can still save even if formatting hangs.
10071        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10072            assert_eq!(
10073                params.text_document.uri,
10074                lsp::Url::from_file_path("/file.rs").unwrap()
10075            );
10076            futures::future::pending::<()>().await;
10077            unreachable!()
10078        });
10079        let save = cx.update(|cx| editor.save(project.clone(), cx));
10080        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10081        cx.foreground().start_waiting();
10082        save.await.unwrap();
10083        assert_eq!(
10084            editor.read_with(cx, |editor, cx| editor.text(cx)),
10085            "one\ntwo\nthree\n"
10086        );
10087        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10088
10089        // Set rust language override and assert overriden tabsize is sent to language server
10090        cx.update(|cx| {
10091            cx.update_global::<Settings, _, _>(|settings, _| {
10092                settings.language_overrides.insert(
10093                    "Rust".into(),
10094                    EditorSettings {
10095                        tab_size: Some(8.try_into().unwrap()),
10096                        ..Default::default()
10097                    },
10098                );
10099            })
10100        });
10101
10102        let save = cx.update(|cx| editor.save(project.clone(), cx));
10103        fake_server
10104            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10105                assert_eq!(
10106                    params.text_document.uri,
10107                    lsp::Url::from_file_path("/file.rs").unwrap()
10108                );
10109                assert_eq!(params.options.tab_size, 8);
10110                Ok(Some(vec![]))
10111            })
10112            .next()
10113            .await;
10114        cx.foreground().start_waiting();
10115        save.await.unwrap();
10116    }
10117
10118    #[gpui::test]
10119    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
10120        cx.foreground().forbid_parking();
10121
10122        let mut language = Language::new(
10123            LanguageConfig {
10124                name: "Rust".into(),
10125                path_suffixes: vec!["rs".to_string()],
10126                ..Default::default()
10127            },
10128            Some(tree_sitter_rust::language()),
10129        );
10130        let mut fake_servers = language
10131            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10132                capabilities: lsp::ServerCapabilities {
10133                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
10134                    ..Default::default()
10135                },
10136                ..Default::default()
10137            }))
10138            .await;
10139
10140        let fs = FakeFs::new(cx.background().clone());
10141        fs.insert_file("/file.rs", Default::default()).await;
10142
10143        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10144        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10145        let buffer = project
10146            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10147            .await
10148            .unwrap();
10149
10150        cx.foreground().start_waiting();
10151        let fake_server = fake_servers.next().await.unwrap();
10152
10153        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10154        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10155        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10156        assert!(cx.read(|cx| editor.is_dirty(cx)));
10157
10158        let save = cx.update(|cx| editor.save(project.clone(), cx));
10159        fake_server
10160            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10161                assert_eq!(
10162                    params.text_document.uri,
10163                    lsp::Url::from_file_path("/file.rs").unwrap()
10164                );
10165                assert_eq!(params.options.tab_size, 4);
10166                Ok(Some(vec![lsp::TextEdit::new(
10167                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10168                    ", ".to_string(),
10169                )]))
10170            })
10171            .next()
10172            .await;
10173        cx.foreground().start_waiting();
10174        save.await.unwrap();
10175        assert_eq!(
10176            editor.read_with(cx, |editor, cx| editor.text(cx)),
10177            "one, two\nthree\n"
10178        );
10179        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10180
10181        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10182        assert!(cx.read(|cx| editor.is_dirty(cx)));
10183
10184        // Ensure we can still save even if formatting hangs.
10185        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
10186            move |params, _| async move {
10187                assert_eq!(
10188                    params.text_document.uri,
10189                    lsp::Url::from_file_path("/file.rs").unwrap()
10190                );
10191                futures::future::pending::<()>().await;
10192                unreachable!()
10193            },
10194        );
10195        let save = cx.update(|cx| editor.save(project.clone(), cx));
10196        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
10197        cx.foreground().start_waiting();
10198        save.await.unwrap();
10199        assert_eq!(
10200            editor.read_with(cx, |editor, cx| editor.text(cx)),
10201            "one\ntwo\nthree\n"
10202        );
10203        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10204
10205        // Set rust language override and assert overriden tabsize is sent to language server
10206        cx.update(|cx| {
10207            cx.update_global::<Settings, _, _>(|settings, _| {
10208                settings.language_overrides.insert(
10209                    "Rust".into(),
10210                    EditorSettings {
10211                        tab_size: Some(8.try_into().unwrap()),
10212                        ..Default::default()
10213                    },
10214                );
10215            })
10216        });
10217
10218        let save = cx.update(|cx| editor.save(project.clone(), cx));
10219        fake_server
10220            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10221                assert_eq!(
10222                    params.text_document.uri,
10223                    lsp::Url::from_file_path("/file.rs").unwrap()
10224                );
10225                assert_eq!(params.options.tab_size, 8);
10226                Ok(Some(vec![]))
10227            })
10228            .next()
10229            .await;
10230        cx.foreground().start_waiting();
10231        save.await.unwrap();
10232    }
10233
10234    #[gpui::test]
10235    async fn test_completion(cx: &mut gpui::TestAppContext) {
10236        let mut cx = EditorLspTestContext::new_rust(
10237            lsp::ServerCapabilities {
10238                completion_provider: Some(lsp::CompletionOptions {
10239                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
10240                    ..Default::default()
10241                }),
10242                ..Default::default()
10243            },
10244            cx,
10245        )
10246        .await;
10247
10248        cx.set_state(indoc! {"
10249            oneˇ
10250            two
10251            three
10252        "});
10253        cx.simulate_keystroke(".");
10254        handle_completion_request(
10255            &mut cx,
10256            indoc! {"
10257                one.|<>
10258                two
10259                three
10260            "},
10261            vec!["first_completion", "second_completion"],
10262        )
10263        .await;
10264        cx.condition(|editor, _| editor.context_menu_visible())
10265            .await;
10266        let apply_additional_edits = cx.update_editor(|editor, cx| {
10267            editor.move_down(&MoveDown, cx);
10268            editor
10269                .confirm_completion(&ConfirmCompletion::default(), cx)
10270                .unwrap()
10271        });
10272        cx.assert_editor_state(indoc! {"
10273            one.second_completionˇ
10274            two
10275            three
10276        "});
10277
10278        handle_resolve_completion_request(
10279            &mut cx,
10280            Some((
10281                indoc! {"
10282                    one.second_completion
10283                    two
10284                    threeˇ
10285                "},
10286                "\nadditional edit",
10287            )),
10288        )
10289        .await;
10290        apply_additional_edits.await.unwrap();
10291        cx.assert_editor_state(indoc! {"
10292            one.second_completionˇ
10293            two
10294            three
10295            additional edit
10296        "});
10297
10298        cx.set_state(indoc! {"
10299            one.second_completion
10300            twoˇ
10301            threeˇ
10302            additional edit
10303        "});
10304        cx.simulate_keystroke(" ");
10305        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10306        cx.simulate_keystroke("s");
10307        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10308
10309        cx.assert_editor_state(indoc! {"
10310            one.second_completion
10311            two sˇ
10312            three sˇ
10313            additional edit
10314        "});
10315        //
10316        handle_completion_request(
10317            &mut cx,
10318            indoc! {"
10319                one.second_completion
10320                two s
10321                three <s|>
10322                additional edit
10323            "},
10324            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10325        )
10326        .await;
10327        cx.condition(|editor, _| editor.context_menu_visible())
10328            .await;
10329
10330        cx.simulate_keystroke("i");
10331
10332        handle_completion_request(
10333            &mut cx,
10334            indoc! {"
10335                one.second_completion
10336                two si
10337                three <si|>
10338                additional edit
10339            "},
10340            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10341        )
10342        .await;
10343        cx.condition(|editor, _| editor.context_menu_visible())
10344            .await;
10345
10346        let apply_additional_edits = cx.update_editor(|editor, cx| {
10347            editor
10348                .confirm_completion(&ConfirmCompletion::default(), cx)
10349                .unwrap()
10350        });
10351        cx.assert_editor_state(indoc! {"
10352            one.second_completion
10353            two sixth_completionˇ
10354            three sixth_completionˇ
10355            additional edit
10356        "});
10357
10358        handle_resolve_completion_request(&mut cx, None).await;
10359        apply_additional_edits.await.unwrap();
10360
10361        cx.update(|cx| {
10362            cx.update_global::<Settings, _, _>(|settings, _| {
10363                settings.show_completions_on_input = false;
10364            })
10365        });
10366        cx.set_state("editorˇ");
10367        cx.simulate_keystroke(".");
10368        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10369        cx.simulate_keystroke("c");
10370        cx.simulate_keystroke("l");
10371        cx.simulate_keystroke("o");
10372        cx.assert_editor_state("editor.cloˇ");
10373        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10374        cx.update_editor(|editor, cx| {
10375            editor.show_completions(&ShowCompletions, cx);
10376        });
10377        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
10378        cx.condition(|editor, _| editor.context_menu_visible())
10379            .await;
10380        let apply_additional_edits = cx.update_editor(|editor, cx| {
10381            editor
10382                .confirm_completion(&ConfirmCompletion::default(), cx)
10383                .unwrap()
10384        });
10385        cx.assert_editor_state("editor.closeˇ");
10386        handle_resolve_completion_request(&mut cx, None).await;
10387        apply_additional_edits.await.unwrap();
10388
10389        // Handle completion request passing a marked string specifying where the completion
10390        // should be triggered from using '|' character, what range should be replaced, and what completions
10391        // should be returned using '<' and '>' to delimit the range
10392        async fn handle_completion_request<'a>(
10393            cx: &mut EditorLspTestContext<'a>,
10394            marked_string: &str,
10395            completions: Vec<&'static str>,
10396        ) {
10397            let complete_from_marker: TextRangeMarker = '|'.into();
10398            let replace_range_marker: TextRangeMarker = ('<', '>').into();
10399            let (_, mut marked_ranges) = marked_text_ranges_by(
10400                marked_string,
10401                vec![complete_from_marker.clone(), replace_range_marker.clone()],
10402            );
10403
10404            let complete_from_position =
10405                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
10406            let replace_range =
10407                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10408
10409            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
10410                let completions = completions.clone();
10411                async move {
10412                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
10413                    assert_eq!(
10414                        params.text_document_position.position,
10415                        complete_from_position
10416                    );
10417                    Ok(Some(lsp::CompletionResponse::Array(
10418                        completions
10419                            .iter()
10420                            .map(|completion_text| lsp::CompletionItem {
10421                                label: completion_text.to_string(),
10422                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
10423                                    range: replace_range.clone(),
10424                                    new_text: completion_text.to_string(),
10425                                })),
10426                                ..Default::default()
10427                            })
10428                            .collect(),
10429                    )))
10430                }
10431            })
10432            .next()
10433            .await;
10434        }
10435
10436        async fn handle_resolve_completion_request<'a>(
10437            cx: &mut EditorLspTestContext<'a>,
10438            edit: Option<(&'static str, &'static str)>,
10439        ) {
10440            let edit = edit.map(|(marked_string, new_text)| {
10441                let (_, marked_ranges) = marked_text_ranges(marked_string, false);
10442                let replace_range = cx.to_lsp_range(marked_ranges[0].clone());
10443                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
10444            });
10445
10446            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
10447                let edit = edit.clone();
10448                async move {
10449                    Ok(lsp::CompletionItem {
10450                        additional_text_edits: edit,
10451                        ..Default::default()
10452                    })
10453                }
10454            })
10455            .next()
10456            .await;
10457        }
10458    }
10459
10460    #[gpui::test]
10461    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
10462        cx.update(|cx| cx.set_global(Settings::test(cx)));
10463        let language = Arc::new(Language::new(
10464            LanguageConfig {
10465                line_comment: Some("// ".to_string()),
10466                ..Default::default()
10467            },
10468            Some(tree_sitter_rust::language()),
10469        ));
10470
10471        let text = "
10472            fn a() {
10473                //b();
10474                // c();
10475                //  d();
10476            }
10477        "
10478        .unindent();
10479
10480        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10481        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10482        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10483
10484        view.update(cx, |editor, cx| {
10485            // If multiple selections intersect a line, the line is only
10486            // toggled once.
10487            editor.change_selections(None, cx, |s| {
10488                s.select_display_ranges([
10489                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
10490                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
10491                ])
10492            });
10493            editor.toggle_comments(&ToggleComments, cx);
10494            assert_eq!(
10495                editor.text(cx),
10496                "
10497                    fn a() {
10498                        b();
10499                        c();
10500                         d();
10501                    }
10502                "
10503                .unindent()
10504            );
10505
10506            // The comment prefix is inserted at the same column for every line
10507            // in a selection.
10508            editor.change_selections(None, cx, |s| {
10509                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
10510            });
10511            editor.toggle_comments(&ToggleComments, cx);
10512            assert_eq!(
10513                editor.text(cx),
10514                "
10515                    fn a() {
10516                        // b();
10517                        // c();
10518                        //  d();
10519                    }
10520                "
10521                .unindent()
10522            );
10523
10524            // If a selection ends at the beginning of a line, that line is not toggled.
10525            editor.change_selections(None, cx, |s| {
10526                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
10527            });
10528            editor.toggle_comments(&ToggleComments, cx);
10529            assert_eq!(
10530                editor.text(cx),
10531                "
10532                        fn a() {
10533                            // b();
10534                            c();
10535                            //  d();
10536                        }
10537                    "
10538                .unindent()
10539            );
10540        });
10541    }
10542
10543    #[gpui::test]
10544    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
10545        cx.set_global(Settings::test(cx));
10546        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10547        let multibuffer = cx.add_model(|cx| {
10548            let mut multibuffer = MultiBuffer::new(0);
10549            multibuffer.push_excerpts(
10550                buffer.clone(),
10551                [
10552                    ExcerptRange {
10553                        context: Point::new(0, 0)..Point::new(0, 4),
10554                        primary: None,
10555                    },
10556                    ExcerptRange {
10557                        context: Point::new(1, 0)..Point::new(1, 4),
10558                        primary: None,
10559                    },
10560                ],
10561                cx,
10562            );
10563            multibuffer
10564        });
10565
10566        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
10567
10568        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10569        view.update(cx, |view, cx| {
10570            assert_eq!(view.text(cx), "aaaa\nbbbb");
10571            view.change_selections(None, cx, |s| {
10572                s.select_ranges([
10573                    Point::new(0, 0)..Point::new(0, 0),
10574                    Point::new(1, 0)..Point::new(1, 0),
10575                ])
10576            });
10577
10578            view.handle_input("X", cx);
10579            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
10580            assert_eq!(
10581                view.selections.ranges(cx),
10582                [
10583                    Point::new(0, 1)..Point::new(0, 1),
10584                    Point::new(1, 1)..Point::new(1, 1),
10585                ]
10586            )
10587        });
10588    }
10589
10590    #[gpui::test]
10591    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
10592        cx.set_global(Settings::test(cx));
10593        let markers = vec![('[', ']').into(), ('(', ')').into()];
10594        let (initial_text, mut excerpt_ranges) = marked_text_ranges_by(
10595            indoc! {"
10596                [aaaa
10597                (bbbb]
10598                cccc)",
10599            },
10600            markers.clone(),
10601        );
10602        let excerpt_ranges = markers.into_iter().map(|marker| {
10603            let context = excerpt_ranges.remove(&marker).unwrap()[0].clone();
10604            ExcerptRange {
10605                context,
10606                primary: None,
10607            }
10608        });
10609        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
10610        let multibuffer = cx.add_model(|cx| {
10611            let mut multibuffer = MultiBuffer::new(0);
10612            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
10613            multibuffer
10614        });
10615
10616        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10617        view.update(cx, |view, cx| {
10618            let (expected_text, selection_ranges) = marked_text_ranges(
10619                indoc! {"
10620                    aaaa
10621                    bˇbbb
10622                    bˇbbˇb
10623                    cccc"
10624                },
10625                true,
10626            );
10627            assert_eq!(view.text(cx), expected_text);
10628            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
10629
10630            view.handle_input("X", cx);
10631
10632            let (expected_text, expected_selections) = marked_text_ranges(
10633                indoc! {"
10634                    aaaa
10635                    bXˇbbXb
10636                    bXˇbbXˇb
10637                    cccc"
10638                },
10639                false,
10640            );
10641            assert_eq!(view.text(cx), expected_text);
10642            assert_eq!(view.selections.ranges(cx), expected_selections);
10643
10644            view.newline(&Newline, cx);
10645            let (expected_text, expected_selections) = marked_text_ranges(
10646                indoc! {"
10647                    aaaa
10648                    bX
10649                    ˇbbX
10650                    b
10651                    bX
10652                    ˇbbX
10653                    ˇb
10654                    cccc"
10655                },
10656                false,
10657            );
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) = marked_text_ranges(marked_text, true);
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}