editor.rs

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