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                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5853                    s.select_ranges([cursor..cursor]);
 5854                });
 5855                Some(())
 5856            })?;
 5857            Some(())
 5858        })
 5859        .detach()
 5860    }
 5861}
 5862
 5863impl EditorSnapshot {
 5864    pub fn is_focused(&self) -> bool {
 5865        self.is_focused
 5866    }
 5867
 5868    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5869        self.placeholder_text.as_ref()
 5870    }
 5871
 5872    pub fn scroll_position(&self) -> Vector2F {
 5873        compute_scroll_position(
 5874            &self.display_snapshot,
 5875            self.scroll_position,
 5876            &self.scroll_top_anchor,
 5877        )
 5878    }
 5879}
 5880
 5881impl Deref for EditorSnapshot {
 5882    type Target = DisplaySnapshot;
 5883
 5884    fn deref(&self) -> &Self::Target {
 5885        &self.display_snapshot
 5886    }
 5887}
 5888
 5889fn compute_scroll_position(
 5890    snapshot: &DisplaySnapshot,
 5891    mut scroll_position: Vector2F,
 5892    scroll_top_anchor: &Anchor,
 5893) -> Vector2F {
 5894    if *scroll_top_anchor != Anchor::min() {
 5895        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5896        scroll_position.set_y(scroll_top + scroll_position.y());
 5897    } else {
 5898        scroll_position.set_y(0.);
 5899    }
 5900    scroll_position
 5901}
 5902
 5903#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5904pub enum Event {
 5905    Activate,
 5906    BufferEdited,
 5907    Edited,
 5908    Reparsed,
 5909    Blurred,
 5910    Dirtied,
 5911    Saved,
 5912    TitleChanged,
 5913    SelectionsChanged { local: bool },
 5914    ScrollPositionChanged { local: bool },
 5915    Closed,
 5916}
 5917
 5918pub struct EditorFocused(pub ViewHandle<Editor>);
 5919pub struct EditorBlurred(pub ViewHandle<Editor>);
 5920pub struct EditorReleased(pub WeakViewHandle<Editor>);
 5921
 5922impl Entity for Editor {
 5923    type Event = Event;
 5924
 5925    fn release(&mut self, cx: &mut MutableAppContext) {
 5926        cx.emit_global(EditorReleased(self.handle.clone()));
 5927    }
 5928}
 5929
 5930impl View for Editor {
 5931    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 5932        let style = self.style(cx);
 5933        self.display_map.update(cx, |map, cx| {
 5934            map.set_font(style.text.font_id, style.text.font_size, cx)
 5935        });
 5936        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 5937    }
 5938
 5939    fn ui_name() -> &'static str {
 5940        "Editor"
 5941    }
 5942
 5943    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 5944        let focused_event = EditorFocused(cx.handle());
 5945        cx.emit_global(focused_event);
 5946        if let Some(rename) = self.pending_rename.as_ref() {
 5947            cx.focus(&rename.editor);
 5948        } else {
 5949            self.focused = true;
 5950            self.blink_cursors(self.blink_epoch, cx);
 5951            self.buffer.update(cx, |buffer, cx| {
 5952                buffer.finalize_last_transaction(cx);
 5953                if self.leader_replica_id.is_none() {
 5954                    buffer.set_active_selections(
 5955                        &self.selections.disjoint_anchors(),
 5956                        self.selections.line_mode,
 5957                        cx,
 5958                    );
 5959                }
 5960            });
 5961        }
 5962    }
 5963
 5964    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 5965        let blurred_event = EditorBlurred(cx.handle());
 5966        cx.emit_global(blurred_event);
 5967        self.focused = false;
 5968        self.buffer
 5969            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 5970        self.hide_context_menu(cx);
 5971        cx.emit(Event::Blurred);
 5972        cx.notify();
 5973    }
 5974
 5975    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 5976        let mut context = Self::default_keymap_context();
 5977        let mode = match self.mode {
 5978            EditorMode::SingleLine => "single_line",
 5979            EditorMode::AutoHeight { .. } => "auto_height",
 5980            EditorMode::Full => "full",
 5981        };
 5982        context.map.insert("mode".into(), mode.into());
 5983        if self.pending_rename.is_some() {
 5984            context.set.insert("renaming".into());
 5985        }
 5986        match self.context_menu.as_ref() {
 5987            Some(ContextMenu::Completions(_)) => {
 5988                context.set.insert("showing_completions".into());
 5989            }
 5990            Some(ContextMenu::CodeActions(_)) => {
 5991                context.set.insert("showing_code_actions".into());
 5992            }
 5993            None => {}
 5994        }
 5995
 5996        for layer in self.keymap_context_layers.values() {
 5997            context.extend(layer);
 5998        }
 5999
 6000        context
 6001    }
 6002}
 6003
 6004fn build_style(
 6005    settings: &Settings,
 6006    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6007    override_text_style: Option<&OverrideTextStyle>,
 6008    cx: &AppContext,
 6009) -> EditorStyle {
 6010    let font_cache = cx.font_cache();
 6011
 6012    let mut theme = settings.theme.editor.clone();
 6013    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6014        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6015        theme.text_color = field_editor_theme.text.color;
 6016        theme.selection = field_editor_theme.selection;
 6017        theme.background = field_editor_theme
 6018            .container
 6019            .background_color
 6020            .unwrap_or_default();
 6021        EditorStyle {
 6022            text: field_editor_theme.text,
 6023            placeholder_text: field_editor_theme.placeholder_text,
 6024            theme,
 6025        }
 6026    } else {
 6027        let font_family_id = settings.buffer_font_family;
 6028        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6029        let font_properties = Default::default();
 6030        let font_id = font_cache
 6031            .select_font(font_family_id, &font_properties)
 6032            .unwrap();
 6033        let font_size = settings.buffer_font_size;
 6034        EditorStyle {
 6035            text: TextStyle {
 6036                color: settings.theme.editor.text_color,
 6037                font_family_name,
 6038                font_family_id,
 6039                font_id,
 6040                font_size,
 6041                font_properties,
 6042                underline: Default::default(),
 6043            },
 6044            placeholder_text: None,
 6045            theme,
 6046        }
 6047    };
 6048
 6049    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6050        if let Some(highlighted) = style
 6051            .text
 6052            .clone()
 6053            .highlight(highlight_style, font_cache)
 6054            .log_err()
 6055        {
 6056            style.text = highlighted;
 6057        }
 6058    }
 6059
 6060    style
 6061}
 6062
 6063trait SelectionExt {
 6064    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6065    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6066    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6067    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6068        -> Range<u32>;
 6069}
 6070
 6071impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6072    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6073        let start = self.start.to_point(buffer);
 6074        let end = self.end.to_point(buffer);
 6075        if self.reversed {
 6076            end..start
 6077        } else {
 6078            start..end
 6079        }
 6080    }
 6081
 6082    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6083        let start = self.start.to_offset(buffer);
 6084        let end = self.end.to_offset(buffer);
 6085        if self.reversed {
 6086            end..start
 6087        } else {
 6088            start..end
 6089        }
 6090    }
 6091
 6092    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6093        let start = self
 6094            .start
 6095            .to_point(&map.buffer_snapshot)
 6096            .to_display_point(map);
 6097        let end = self
 6098            .end
 6099            .to_point(&map.buffer_snapshot)
 6100            .to_display_point(map);
 6101        if self.reversed {
 6102            end..start
 6103        } else {
 6104            start..end
 6105        }
 6106    }
 6107
 6108    fn spanned_rows(
 6109        &self,
 6110        include_end_if_at_line_start: bool,
 6111        map: &DisplaySnapshot,
 6112    ) -> Range<u32> {
 6113        let start = self.start.to_point(&map.buffer_snapshot);
 6114        let mut end = self.end.to_point(&map.buffer_snapshot);
 6115        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6116            end.row -= 1;
 6117        }
 6118
 6119        let buffer_start = map.prev_line_boundary(start).0;
 6120        let buffer_end = map.next_line_boundary(end).0;
 6121        buffer_start.row..buffer_end.row + 1
 6122    }
 6123}
 6124
 6125impl<T: InvalidationRegion> InvalidationStack<T> {
 6126    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6127    where
 6128        S: Clone + ToOffset,
 6129    {
 6130        while let Some(region) = self.last() {
 6131            let all_selections_inside_invalidation_ranges =
 6132                if selections.len() == region.ranges().len() {
 6133                    selections
 6134                        .iter()
 6135                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6136                        .all(|(selection, invalidation_range)| {
 6137                            let head = selection.head().to_offset(&buffer);
 6138                            invalidation_range.start <= head && invalidation_range.end >= head
 6139                        })
 6140                } else {
 6141                    false
 6142                };
 6143
 6144            if all_selections_inside_invalidation_ranges {
 6145                break;
 6146            } else {
 6147                self.pop();
 6148            }
 6149        }
 6150    }
 6151}
 6152
 6153impl<T> Default for InvalidationStack<T> {
 6154    fn default() -> Self {
 6155        Self(Default::default())
 6156    }
 6157}
 6158
 6159impl<T> Deref for InvalidationStack<T> {
 6160    type Target = Vec<T>;
 6161
 6162    fn deref(&self) -> &Self::Target {
 6163        &self.0
 6164    }
 6165}
 6166
 6167impl<T> DerefMut for InvalidationStack<T> {
 6168    fn deref_mut(&mut self) -> &mut Self::Target {
 6169        &mut self.0
 6170    }
 6171}
 6172
 6173impl InvalidationRegion for BracketPairState {
 6174    fn ranges(&self) -> &[Range<Anchor>] {
 6175        &self.ranges
 6176    }
 6177}
 6178
 6179impl InvalidationRegion for SnippetState {
 6180    fn ranges(&self) -> &[Range<Anchor>] {
 6181        &self.ranges[self.active_index]
 6182    }
 6183}
 6184
 6185impl Deref for EditorStyle {
 6186    type Target = theme::Editor;
 6187
 6188    fn deref(&self) -> &Self::Target {
 6189        &self.theme
 6190    }
 6191}
 6192
 6193pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6194    let mut highlighted_lines = Vec::new();
 6195    for line in diagnostic.message.lines() {
 6196        highlighted_lines.push(highlight_diagnostic_message(line));
 6197    }
 6198
 6199    Arc::new(move |cx: &mut BlockContext| {
 6200        let settings = cx.global::<Settings>();
 6201        let theme = &settings.theme.editor;
 6202        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6203        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6204        Flex::column()
 6205            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6206                Label::new(
 6207                    line.clone(),
 6208                    style.message.clone().with_font_size(font_size),
 6209                )
 6210                .with_highlights(highlights.clone())
 6211                .contained()
 6212                .with_margin_left(cx.anchor_x)
 6213                .boxed()
 6214            }))
 6215            .aligned()
 6216            .left()
 6217            .boxed()
 6218    })
 6219}
 6220
 6221pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6222    let mut message_without_backticks = String::new();
 6223    let mut prev_offset = 0;
 6224    let mut inside_block = false;
 6225    let mut highlights = Vec::new();
 6226    for (match_ix, (offset, _)) in message
 6227        .match_indices('`')
 6228        .chain([(message.len(), "")])
 6229        .enumerate()
 6230    {
 6231        message_without_backticks.push_str(&message[prev_offset..offset]);
 6232        if inside_block {
 6233            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6234        }
 6235
 6236        inside_block = !inside_block;
 6237        prev_offset = offset + 1;
 6238    }
 6239
 6240    (message_without_backticks, highlights)
 6241}
 6242
 6243pub fn diagnostic_style(
 6244    severity: DiagnosticSeverity,
 6245    valid: bool,
 6246    theme: &theme::Editor,
 6247) -> DiagnosticStyle {
 6248    match (severity, valid) {
 6249        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6250        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6251        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6252        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6253        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6254        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6255        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6256        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6257        _ => theme.invalid_hint_diagnostic.clone(),
 6258    }
 6259}
 6260
 6261pub fn combine_syntax_and_fuzzy_match_highlights(
 6262    text: &str,
 6263    default_style: HighlightStyle,
 6264    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6265    match_indices: &[usize],
 6266) -> Vec<(Range<usize>, HighlightStyle)> {
 6267    let mut result = Vec::new();
 6268    let mut match_indices = match_indices.iter().copied().peekable();
 6269
 6270    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6271    {
 6272        syntax_highlight.weight = None;
 6273
 6274        // Add highlights for any fuzzy match characters before the next
 6275        // syntax highlight range.
 6276        while let Some(&match_index) = match_indices.peek() {
 6277            if match_index >= range.start {
 6278                break;
 6279            }
 6280            match_indices.next();
 6281            let end_index = char_ix_after(match_index, text);
 6282            let mut match_style = default_style;
 6283            match_style.weight = Some(fonts::Weight::BOLD);
 6284            result.push((match_index..end_index, match_style));
 6285        }
 6286
 6287        if range.start == usize::MAX {
 6288            break;
 6289        }
 6290
 6291        // Add highlights for any fuzzy match characters within the
 6292        // syntax highlight range.
 6293        let mut offset = range.start;
 6294        while let Some(&match_index) = match_indices.peek() {
 6295            if match_index >= range.end {
 6296                break;
 6297            }
 6298
 6299            match_indices.next();
 6300            if match_index > offset {
 6301                result.push((offset..match_index, syntax_highlight));
 6302            }
 6303
 6304            let mut end_index = char_ix_after(match_index, text);
 6305            while let Some(&next_match_index) = match_indices.peek() {
 6306                if next_match_index == end_index && next_match_index < range.end {
 6307                    end_index = char_ix_after(next_match_index, text);
 6308                    match_indices.next();
 6309                } else {
 6310                    break;
 6311                }
 6312            }
 6313
 6314            let mut match_style = syntax_highlight;
 6315            match_style.weight = Some(fonts::Weight::BOLD);
 6316            result.push((match_index..end_index, match_style));
 6317            offset = end_index;
 6318        }
 6319
 6320        if offset < range.end {
 6321            result.push((offset..range.end, syntax_highlight));
 6322        }
 6323    }
 6324
 6325    fn char_ix_after(ix: usize, text: &str) -> usize {
 6326        ix + text[ix..].chars().next().unwrap().len_utf8()
 6327    }
 6328
 6329    result
 6330}
 6331
 6332pub fn styled_runs_for_code_label<'a>(
 6333    label: &'a CodeLabel,
 6334    syntax_theme: &'a theme::SyntaxTheme,
 6335) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6336    let fade_out = HighlightStyle {
 6337        fade_out: Some(0.35),
 6338        ..Default::default()
 6339    };
 6340
 6341    let mut prev_end = label.filter_range.end;
 6342    label
 6343        .runs
 6344        .iter()
 6345        .enumerate()
 6346        .flat_map(move |(ix, (range, highlight_id))| {
 6347            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6348                style
 6349            } else {
 6350                return Default::default();
 6351            };
 6352            let mut muted_style = style.clone();
 6353            muted_style.highlight(fade_out);
 6354
 6355            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6356            if range.start >= label.filter_range.end {
 6357                if range.start > prev_end {
 6358                    runs.push((prev_end..range.start, fade_out));
 6359                }
 6360                runs.push((range.clone(), muted_style));
 6361            } else if range.end <= label.filter_range.end {
 6362                runs.push((range.clone(), style));
 6363            } else {
 6364                runs.push((range.start..label.filter_range.end, style));
 6365                runs.push((label.filter_range.end..range.end, muted_style));
 6366            }
 6367            prev_end = cmp::max(prev_end, range.end);
 6368
 6369            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6370                runs.push((prev_end..label.text.len(), fade_out));
 6371            }
 6372
 6373            runs
 6374        })
 6375}
 6376
 6377#[cfg(test)]
 6378mod tests {
 6379    use crate::test::{
 6380        assert_text_with_selections, build_editor, select_ranges, EditorTestContext,
 6381    };
 6382
 6383    use super::*;
 6384    use gpui::{
 6385        geometry::rect::RectF,
 6386        platform::{WindowBounds, WindowOptions},
 6387    };
 6388    use indoc::indoc;
 6389    use language::{FakeLspAdapter, LanguageConfig};
 6390    use lsp::FakeLanguageServer;
 6391    use project::FakeFs;
 6392    use settings::LanguageOverride;
 6393    use smol::stream::StreamExt;
 6394    use std::{cell::RefCell, rc::Rc, time::Instant};
 6395    use text::Point;
 6396    use unindent::Unindent;
 6397    use util::{
 6398        assert_set_eq,
 6399        test::{marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text},
 6400    };
 6401    use workspace::{FollowableItem, ItemHandle};
 6402
 6403    #[gpui::test]
 6404    fn test_edit_events(cx: &mut MutableAppContext) {
 6405        cx.set_global(Settings::test(cx));
 6406        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6407
 6408        let events = Rc::new(RefCell::new(Vec::new()));
 6409        let (_, editor1) = cx.add_window(Default::default(), {
 6410            let events = events.clone();
 6411            |cx| {
 6412                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6413                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6414                        events.borrow_mut().push(("editor1", *event));
 6415                    }
 6416                })
 6417                .detach();
 6418                Editor::for_buffer(buffer.clone(), None, cx)
 6419            }
 6420        });
 6421        let (_, editor2) = cx.add_window(Default::default(), {
 6422            let events = events.clone();
 6423            |cx| {
 6424                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6425                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6426                        events.borrow_mut().push(("editor2", *event));
 6427                    }
 6428                })
 6429                .detach();
 6430                Editor::for_buffer(buffer.clone(), None, cx)
 6431            }
 6432        });
 6433        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6434
 6435        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6436        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6437        assert_eq!(
 6438            mem::take(&mut *events.borrow_mut()),
 6439            [
 6440                ("editor1", Event::Edited),
 6441                ("editor1", Event::BufferEdited),
 6442                ("editor2", Event::BufferEdited),
 6443                ("editor1", Event::Dirtied),
 6444                ("editor2", Event::Dirtied)
 6445            ]
 6446        );
 6447
 6448        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6449        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6450        assert_eq!(
 6451            mem::take(&mut *events.borrow_mut()),
 6452            [
 6453                ("editor2", Event::Edited),
 6454                ("editor1", Event::BufferEdited),
 6455                ("editor2", Event::BufferEdited),
 6456            ]
 6457        );
 6458
 6459        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6460        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6461        assert_eq!(
 6462            mem::take(&mut *events.borrow_mut()),
 6463            [
 6464                ("editor1", Event::Edited),
 6465                ("editor1", Event::BufferEdited),
 6466                ("editor2", Event::BufferEdited),
 6467            ]
 6468        );
 6469
 6470        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6471        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6472        assert_eq!(
 6473            mem::take(&mut *events.borrow_mut()),
 6474            [
 6475                ("editor1", Event::Edited),
 6476                ("editor1", Event::BufferEdited),
 6477                ("editor2", Event::BufferEdited),
 6478            ]
 6479        );
 6480
 6481        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6482        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6483        assert_eq!(
 6484            mem::take(&mut *events.borrow_mut()),
 6485            [
 6486                ("editor2", Event::Edited),
 6487                ("editor1", Event::BufferEdited),
 6488                ("editor2", Event::BufferEdited),
 6489            ]
 6490        );
 6491
 6492        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6493        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6494        assert_eq!(
 6495            mem::take(&mut *events.borrow_mut()),
 6496            [
 6497                ("editor2", Event::Edited),
 6498                ("editor1", Event::BufferEdited),
 6499                ("editor2", Event::BufferEdited),
 6500            ]
 6501        );
 6502
 6503        // No event is emitted when the mutation is a no-op.
 6504        editor2.update(cx, |editor, cx| {
 6505            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6506
 6507            editor.backspace(&Backspace, cx);
 6508        });
 6509        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6510    }
 6511
 6512    #[gpui::test]
 6513    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6514        cx.set_global(Settings::test(cx));
 6515        let mut now = Instant::now();
 6516        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6517        let group_interval = buffer.read(cx).transaction_group_interval();
 6518        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6519        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6520
 6521        editor.update(cx, |editor, cx| {
 6522            editor.start_transaction_at(now, cx);
 6523            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6524
 6525            editor.insert("cd", cx);
 6526            editor.end_transaction_at(now, cx);
 6527            assert_eq!(editor.text(cx), "12cd56");
 6528            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6529
 6530            editor.start_transaction_at(now, cx);
 6531            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6532            editor.insert("e", cx);
 6533            editor.end_transaction_at(now, cx);
 6534            assert_eq!(editor.text(cx), "12cde6");
 6535            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6536
 6537            now += group_interval + Duration::from_millis(1);
 6538            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6539
 6540            // Simulate an edit in another editor
 6541            buffer.update(cx, |buffer, cx| {
 6542                buffer.start_transaction_at(now, cx);
 6543                buffer.edit([(0..1, "a")], cx);
 6544                buffer.edit([(1..1, "b")], cx);
 6545                buffer.end_transaction_at(now, cx);
 6546            });
 6547
 6548            assert_eq!(editor.text(cx), "ab2cde6");
 6549            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6550
 6551            // Last transaction happened past the group interval in a different editor.
 6552            // Undo it individually and don't restore selections.
 6553            editor.undo(&Undo, cx);
 6554            assert_eq!(editor.text(cx), "12cde6");
 6555            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6556
 6557            // First two transactions happened within the group interval in this editor.
 6558            // Undo them together and restore selections.
 6559            editor.undo(&Undo, cx);
 6560            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6561            assert_eq!(editor.text(cx), "123456");
 6562            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6563
 6564            // Redo the first two transactions together.
 6565            editor.redo(&Redo, cx);
 6566            assert_eq!(editor.text(cx), "12cde6");
 6567            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6568
 6569            // Redo the last transaction on its own.
 6570            editor.redo(&Redo, cx);
 6571            assert_eq!(editor.text(cx), "ab2cde6");
 6572            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6573
 6574            // Test empty transactions.
 6575            editor.start_transaction_at(now, cx);
 6576            editor.end_transaction_at(now, cx);
 6577            editor.undo(&Undo, cx);
 6578            assert_eq!(editor.text(cx), "12cde6");
 6579        });
 6580    }
 6581
 6582    #[gpui::test]
 6583    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6584        cx.set_global(Settings::test(cx));
 6585
 6586        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6587        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6588        editor.update(cx, |view, cx| {
 6589            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6590        });
 6591        assert_eq!(
 6592            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6593            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6594        );
 6595
 6596        editor.update(cx, |view, cx| {
 6597            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6598        });
 6599
 6600        assert_eq!(
 6601            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6602            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6603        );
 6604
 6605        editor.update(cx, |view, cx| {
 6606            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6607        });
 6608
 6609        assert_eq!(
 6610            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6611            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6612        );
 6613
 6614        editor.update(cx, |view, cx| {
 6615            view.end_selection(cx);
 6616            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6617        });
 6618
 6619        assert_eq!(
 6620            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6621            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6622        );
 6623
 6624        editor.update(cx, |view, cx| {
 6625            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6626            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6627        });
 6628
 6629        assert_eq!(
 6630            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6631            [
 6632                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6633                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6634            ]
 6635        );
 6636
 6637        editor.update(cx, |view, cx| {
 6638            view.end_selection(cx);
 6639        });
 6640
 6641        assert_eq!(
 6642            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6643            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6644        );
 6645    }
 6646
 6647    #[gpui::test]
 6648    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6649        cx.set_global(Settings::test(cx));
 6650        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6651        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6652
 6653        view.update(cx, |view, cx| {
 6654            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6655            assert_eq!(
 6656                view.selections.display_ranges(cx),
 6657                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6658            );
 6659        });
 6660
 6661        view.update(cx, |view, cx| {
 6662            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6663            assert_eq!(
 6664                view.selections.display_ranges(cx),
 6665                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6666            );
 6667        });
 6668
 6669        view.update(cx, |view, cx| {
 6670            view.cancel(&Cancel, cx);
 6671            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6672            assert_eq!(
 6673                view.selections.display_ranges(cx),
 6674                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6675            );
 6676        });
 6677    }
 6678
 6679    #[gpui::test]
 6680    fn test_clone_with_selections(cx: &mut gpui::MutableAppContext) {
 6681        let (text, selection_ranges) = marked_text_ranges(indoc! {"
 6682            The qu[ick brown
 6683            fox jum]ps over
 6684            the lazy dog
 6685        "});
 6686        cx.set_global(Settings::test(cx));
 6687        let buffer = MultiBuffer::build_simple(&text, cx);
 6688
 6689        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6690
 6691        let cloned_editor = view.update(cx, |view, cx| {
 6692            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 6693            view.clone(cx)
 6694        });
 6695
 6696        assert_set_eq!(cloned_editor.selections.ranges(cx), selection_ranges);
 6697    }
 6698
 6699    #[gpui::test]
 6700    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6701        cx.set_global(Settings::test(cx));
 6702        use workspace::Item;
 6703        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6704        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6705
 6706        cx.add_window(Default::default(), |cx| {
 6707            let mut editor = build_editor(buffer.clone(), cx);
 6708            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6709
 6710            // Move the cursor a small distance.
 6711            // Nothing is added to the navigation history.
 6712            editor.change_selections(None, cx, |s| {
 6713                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 6714            });
 6715            editor.change_selections(None, cx, |s| {
 6716                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 6717            });
 6718            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6719
 6720            // Move the cursor a large distance.
 6721            // The history can jump back to the previous position.
 6722            editor.change_selections(None, cx, |s| {
 6723                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 6724            });
 6725            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6726            editor.navigate(nav_entry.data.unwrap(), cx);
 6727            assert_eq!(nav_entry.item.id(), cx.view_id());
 6728            assert_eq!(
 6729                editor.selections.display_ranges(cx),
 6730                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6731            );
 6732            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6733
 6734            // Move the cursor a small distance via the mouse.
 6735            // Nothing is added to the navigation history.
 6736            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6737            editor.end_selection(cx);
 6738            assert_eq!(
 6739                editor.selections.display_ranges(cx),
 6740                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6741            );
 6742            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6743
 6744            // Move the cursor a large distance via the mouse.
 6745            // The history can jump back to the previous position.
 6746            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6747            editor.end_selection(cx);
 6748            assert_eq!(
 6749                editor.selections.display_ranges(cx),
 6750                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6751            );
 6752            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6753            editor.navigate(nav_entry.data.unwrap(), cx);
 6754            assert_eq!(nav_entry.item.id(), cx.view_id());
 6755            assert_eq!(
 6756                editor.selections.display_ranges(cx),
 6757                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6758            );
 6759            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6760
 6761            // Set scroll position to check later
 6762            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6763            let original_scroll_position = editor.scroll_position;
 6764            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6765
 6766            // Jump to the end of the document and adjust scroll
 6767            editor.move_to_end(&MoveToEnd, cx);
 6768            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6769            assert_ne!(editor.scroll_position, original_scroll_position);
 6770            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6771
 6772            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6773            editor.navigate(nav_entry.data.unwrap(), cx);
 6774            assert_eq!(editor.scroll_position, original_scroll_position);
 6775            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6776
 6777            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6778            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6779            invalid_anchor.text_anchor.buffer_id = Some(999);
 6780            let invalid_point = Point::new(9999, 0);
 6781            editor.navigate(
 6782                Box::new(NavigationData {
 6783                    cursor_anchor: invalid_anchor.clone(),
 6784                    cursor_position: invalid_point,
 6785                    scroll_top_anchor: invalid_anchor.clone(),
 6786                    scroll_top_row: invalid_point.row,
 6787                    scroll_position: Default::default(),
 6788                }),
 6789                cx,
 6790            );
 6791            assert_eq!(
 6792                editor.selections.display_ranges(cx),
 6793                &[editor.max_point(cx)..editor.max_point(cx)]
 6794            );
 6795            assert_eq!(
 6796                editor.scroll_position(cx),
 6797                vec2f(0., editor.max_point(cx).row() as f32)
 6798            );
 6799
 6800            editor
 6801        });
 6802    }
 6803
 6804    #[gpui::test]
 6805    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6806        cx.set_global(Settings::test(cx));
 6807        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6808        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6809
 6810        view.update(cx, |view, cx| {
 6811            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6812            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6813            view.end_selection(cx);
 6814
 6815            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6816            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6817            view.end_selection(cx);
 6818            assert_eq!(
 6819                view.selections.display_ranges(cx),
 6820                [
 6821                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6822                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6823                ]
 6824            );
 6825        });
 6826
 6827        view.update(cx, |view, cx| {
 6828            view.cancel(&Cancel, cx);
 6829            assert_eq!(
 6830                view.selections.display_ranges(cx),
 6831                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6832            );
 6833        });
 6834
 6835        view.update(cx, |view, cx| {
 6836            view.cancel(&Cancel, cx);
 6837            assert_eq!(
 6838                view.selections.display_ranges(cx),
 6839                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6840            );
 6841        });
 6842    }
 6843
 6844    #[gpui::test]
 6845    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6846        cx.set_global(Settings::test(cx));
 6847        let buffer = MultiBuffer::build_simple(
 6848            &"
 6849                impl Foo {
 6850                    // Hello!
 6851
 6852                    fn a() {
 6853                        1
 6854                    }
 6855
 6856                    fn b() {
 6857                        2
 6858                    }
 6859
 6860                    fn c() {
 6861                        3
 6862                    }
 6863                }
 6864            "
 6865            .unindent(),
 6866            cx,
 6867        );
 6868        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6869
 6870        view.update(cx, |view, cx| {
 6871            view.change_selections(None, cx, |s| {
 6872                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 6873            });
 6874            view.fold(&Fold, cx);
 6875            assert_eq!(
 6876                view.display_text(cx),
 6877                "
 6878                    impl Foo {
 6879                        // Hello!
 6880
 6881                        fn a() {
 6882                            1
 6883                        }
 6884
 6885                        fn b() {…
 6886                        }
 6887
 6888                        fn c() {…
 6889                        }
 6890                    }
 6891                "
 6892                .unindent(),
 6893            );
 6894
 6895            view.fold(&Fold, cx);
 6896            assert_eq!(
 6897                view.display_text(cx),
 6898                "
 6899                    impl Foo {…
 6900                    }
 6901                "
 6902                .unindent(),
 6903            );
 6904
 6905            view.unfold_lines(&UnfoldLines, cx);
 6906            assert_eq!(
 6907                view.display_text(cx),
 6908                "
 6909                    impl Foo {
 6910                        // Hello!
 6911
 6912                        fn a() {
 6913                            1
 6914                        }
 6915
 6916                        fn b() {…
 6917                        }
 6918
 6919                        fn c() {…
 6920                        }
 6921                    }
 6922                "
 6923                .unindent(),
 6924            );
 6925
 6926            view.unfold_lines(&UnfoldLines, cx);
 6927            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6928        });
 6929    }
 6930
 6931    #[gpui::test]
 6932    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6933        cx.set_global(Settings::test(cx));
 6934        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6935        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6936
 6937        buffer.update(cx, |buffer, cx| {
 6938            buffer.edit(
 6939                vec![
 6940                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 6941                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 6942                ],
 6943                cx,
 6944            );
 6945        });
 6946
 6947        view.update(cx, |view, cx| {
 6948            assert_eq!(
 6949                view.selections.display_ranges(cx),
 6950                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6951            );
 6952
 6953            view.move_down(&MoveDown, cx);
 6954            assert_eq!(
 6955                view.selections.display_ranges(cx),
 6956                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6957            );
 6958
 6959            view.move_right(&MoveRight, cx);
 6960            assert_eq!(
 6961                view.selections.display_ranges(cx),
 6962                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6963            );
 6964
 6965            view.move_left(&MoveLeft, cx);
 6966            assert_eq!(
 6967                view.selections.display_ranges(cx),
 6968                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6969            );
 6970
 6971            view.move_up(&MoveUp, cx);
 6972            assert_eq!(
 6973                view.selections.display_ranges(cx),
 6974                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6975            );
 6976
 6977            view.move_to_end(&MoveToEnd, cx);
 6978            assert_eq!(
 6979                view.selections.display_ranges(cx),
 6980                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 6981            );
 6982
 6983            view.move_to_beginning(&MoveToBeginning, cx);
 6984            assert_eq!(
 6985                view.selections.display_ranges(cx),
 6986                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6987            );
 6988
 6989            view.change_selections(None, cx, |s| {
 6990                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 6991            });
 6992            view.select_to_beginning(&SelectToBeginning, cx);
 6993            assert_eq!(
 6994                view.selections.display_ranges(cx),
 6995                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 6996            );
 6997
 6998            view.select_to_end(&SelectToEnd, cx);
 6999            assert_eq!(
 7000                view.selections.display_ranges(cx),
 7001                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7002            );
 7003        });
 7004    }
 7005
 7006    #[gpui::test]
 7007    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7008        cx.set_global(Settings::test(cx));
 7009        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7010        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7011
 7012        assert_eq!('ⓐ'.len_utf8(), 3);
 7013        assert_eq!('α'.len_utf8(), 2);
 7014
 7015        view.update(cx, |view, cx| {
 7016            view.fold_ranges(
 7017                vec![
 7018                    Point::new(0, 6)..Point::new(0, 12),
 7019                    Point::new(1, 2)..Point::new(1, 4),
 7020                    Point::new(2, 4)..Point::new(2, 8),
 7021                ],
 7022                cx,
 7023            );
 7024            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7025
 7026            view.move_right(&MoveRight, cx);
 7027            assert_eq!(
 7028                view.selections.display_ranges(cx),
 7029                &[empty_range(0, "".len())]
 7030            );
 7031            view.move_right(&MoveRight, cx);
 7032            assert_eq!(
 7033                view.selections.display_ranges(cx),
 7034                &[empty_range(0, "ⓐⓑ".len())]
 7035            );
 7036            view.move_right(&MoveRight, cx);
 7037            assert_eq!(
 7038                view.selections.display_ranges(cx),
 7039                &[empty_range(0, "ⓐⓑ…".len())]
 7040            );
 7041
 7042            view.move_down(&MoveDown, cx);
 7043            assert_eq!(
 7044                view.selections.display_ranges(cx),
 7045                &[empty_range(1, "ab…".len())]
 7046            );
 7047            view.move_left(&MoveLeft, cx);
 7048            assert_eq!(
 7049                view.selections.display_ranges(cx),
 7050                &[empty_range(1, "ab".len())]
 7051            );
 7052            view.move_left(&MoveLeft, cx);
 7053            assert_eq!(
 7054                view.selections.display_ranges(cx),
 7055                &[empty_range(1, "a".len())]
 7056            );
 7057
 7058            view.move_down(&MoveDown, cx);
 7059            assert_eq!(
 7060                view.selections.display_ranges(cx),
 7061                &[empty_range(2, "α".len())]
 7062            );
 7063            view.move_right(&MoveRight, cx);
 7064            assert_eq!(
 7065                view.selections.display_ranges(cx),
 7066                &[empty_range(2, "αβ".len())]
 7067            );
 7068            view.move_right(&MoveRight, cx);
 7069            assert_eq!(
 7070                view.selections.display_ranges(cx),
 7071                &[empty_range(2, "αβ…".len())]
 7072            );
 7073            view.move_right(&MoveRight, cx);
 7074            assert_eq!(
 7075                view.selections.display_ranges(cx),
 7076                &[empty_range(2, "αβ…ε".len())]
 7077            );
 7078
 7079            view.move_up(&MoveUp, cx);
 7080            assert_eq!(
 7081                view.selections.display_ranges(cx),
 7082                &[empty_range(1, "ab…e".len())]
 7083            );
 7084            view.move_up(&MoveUp, cx);
 7085            assert_eq!(
 7086                view.selections.display_ranges(cx),
 7087                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7088            );
 7089            view.move_left(&MoveLeft, cx);
 7090            assert_eq!(
 7091                view.selections.display_ranges(cx),
 7092                &[empty_range(0, "ⓐⓑ…".len())]
 7093            );
 7094            view.move_left(&MoveLeft, cx);
 7095            assert_eq!(
 7096                view.selections.display_ranges(cx),
 7097                &[empty_range(0, "ⓐⓑ".len())]
 7098            );
 7099            view.move_left(&MoveLeft, cx);
 7100            assert_eq!(
 7101                view.selections.display_ranges(cx),
 7102                &[empty_range(0, "".len())]
 7103            );
 7104        });
 7105    }
 7106
 7107    #[gpui::test]
 7108    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7109        cx.set_global(Settings::test(cx));
 7110        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7111        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7112        view.update(cx, |view, cx| {
 7113            view.change_selections(None, cx, |s| {
 7114                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7115            });
 7116            view.move_down(&MoveDown, cx);
 7117            assert_eq!(
 7118                view.selections.display_ranges(cx),
 7119                &[empty_range(1, "abcd".len())]
 7120            );
 7121
 7122            view.move_down(&MoveDown, cx);
 7123            assert_eq!(
 7124                view.selections.display_ranges(cx),
 7125                &[empty_range(2, "αβγ".len())]
 7126            );
 7127
 7128            view.move_down(&MoveDown, cx);
 7129            assert_eq!(
 7130                view.selections.display_ranges(cx),
 7131                &[empty_range(3, "abcd".len())]
 7132            );
 7133
 7134            view.move_down(&MoveDown, cx);
 7135            assert_eq!(
 7136                view.selections.display_ranges(cx),
 7137                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7138            );
 7139
 7140            view.move_up(&MoveUp, cx);
 7141            assert_eq!(
 7142                view.selections.display_ranges(cx),
 7143                &[empty_range(3, "abcd".len())]
 7144            );
 7145
 7146            view.move_up(&MoveUp, cx);
 7147            assert_eq!(
 7148                view.selections.display_ranges(cx),
 7149                &[empty_range(2, "αβγ".len())]
 7150            );
 7151        });
 7152    }
 7153
 7154    #[gpui::test]
 7155    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7156        cx.set_global(Settings::test(cx));
 7157        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7158        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7159        view.update(cx, |view, cx| {
 7160            view.change_selections(None, cx, |s| {
 7161                s.select_display_ranges([
 7162                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7163                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7164                ]);
 7165            });
 7166        });
 7167
 7168        view.update(cx, |view, cx| {
 7169            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7170            assert_eq!(
 7171                view.selections.display_ranges(cx),
 7172                &[
 7173                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7174                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7175                ]
 7176            );
 7177        });
 7178
 7179        view.update(cx, |view, cx| {
 7180            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7181            assert_eq!(
 7182                view.selections.display_ranges(cx),
 7183                &[
 7184                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7185                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7186                ]
 7187            );
 7188        });
 7189
 7190        view.update(cx, |view, cx| {
 7191            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7192            assert_eq!(
 7193                view.selections.display_ranges(cx),
 7194                &[
 7195                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7196                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7197                ]
 7198            );
 7199        });
 7200
 7201        view.update(cx, |view, cx| {
 7202            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7203            assert_eq!(
 7204                view.selections.display_ranges(cx),
 7205                &[
 7206                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7207                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7208                ]
 7209            );
 7210        });
 7211
 7212        // Moving to the end of line again is a no-op.
 7213        view.update(cx, |view, cx| {
 7214            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7215            assert_eq!(
 7216                view.selections.display_ranges(cx),
 7217                &[
 7218                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7219                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7220                ]
 7221            );
 7222        });
 7223
 7224        view.update(cx, |view, cx| {
 7225            view.move_left(&MoveLeft, cx);
 7226            view.select_to_beginning_of_line(
 7227                &SelectToBeginningOfLine {
 7228                    stop_at_soft_wraps: true,
 7229                },
 7230                cx,
 7231            );
 7232            assert_eq!(
 7233                view.selections.display_ranges(cx),
 7234                &[
 7235                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7236                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7237                ]
 7238            );
 7239        });
 7240
 7241        view.update(cx, |view, cx| {
 7242            view.select_to_beginning_of_line(
 7243                &SelectToBeginningOfLine {
 7244                    stop_at_soft_wraps: true,
 7245                },
 7246                cx,
 7247            );
 7248            assert_eq!(
 7249                view.selections.display_ranges(cx),
 7250                &[
 7251                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7252                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7253                ]
 7254            );
 7255        });
 7256
 7257        view.update(cx, |view, cx| {
 7258            view.select_to_beginning_of_line(
 7259                &SelectToBeginningOfLine {
 7260                    stop_at_soft_wraps: true,
 7261                },
 7262                cx,
 7263            );
 7264            assert_eq!(
 7265                view.selections.display_ranges(cx),
 7266                &[
 7267                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7268                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7269                ]
 7270            );
 7271        });
 7272
 7273        view.update(cx, |view, cx| {
 7274            view.select_to_end_of_line(
 7275                &SelectToEndOfLine {
 7276                    stop_at_soft_wraps: true,
 7277                },
 7278                cx,
 7279            );
 7280            assert_eq!(
 7281                view.selections.display_ranges(cx),
 7282                &[
 7283                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7284                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7285                ]
 7286            );
 7287        });
 7288
 7289        view.update(cx, |view, cx| {
 7290            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7291            assert_eq!(view.display_text(cx), "ab\n  de");
 7292            assert_eq!(
 7293                view.selections.display_ranges(cx),
 7294                &[
 7295                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7296                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7297                ]
 7298            );
 7299        });
 7300
 7301        view.update(cx, |view, cx| {
 7302            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7303            assert_eq!(view.display_text(cx), "\n");
 7304            assert_eq!(
 7305                view.selections.display_ranges(cx),
 7306                &[
 7307                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7308                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7309                ]
 7310            );
 7311        });
 7312    }
 7313
 7314    #[gpui::test]
 7315    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7316        cx.set_global(Settings::test(cx));
 7317        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7318        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7319        view.update(cx, |view, cx| {
 7320            view.change_selections(None, cx, |s| {
 7321                s.select_display_ranges([
 7322                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7323                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7324                ])
 7325            });
 7326
 7327            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7328            assert_selection_ranges(
 7329                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7330                vec![('<', '>'), ('[', ']')],
 7331                view,
 7332                cx,
 7333            );
 7334
 7335            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7336            assert_selection_ranges(
 7337                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7338                vec![('<', '>'), ('[', ']')],
 7339                view,
 7340                cx,
 7341            );
 7342
 7343            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7344            assert_selection_ranges(
 7345                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7346                vec![('<', '>'), ('[', ']')],
 7347                view,
 7348                cx,
 7349            );
 7350
 7351            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7352            assert_selection_ranges(
 7353                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7354                vec![('<', '>'), ('[', ']')],
 7355                view,
 7356                cx,
 7357            );
 7358
 7359            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7360            assert_selection_ranges(
 7361                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7362                vec![('<', '>'), ('[', ']')],
 7363                view,
 7364                cx,
 7365            );
 7366
 7367            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7368            assert_selection_ranges(
 7369                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7370                vec![('<', '>'), ('[', ']')],
 7371                view,
 7372                cx,
 7373            );
 7374
 7375            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7376            assert_selection_ranges(
 7377                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7378                vec![('<', '>'), ('[', ']')],
 7379                view,
 7380                cx,
 7381            );
 7382
 7383            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7384            assert_selection_ranges(
 7385                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7386                vec![('<', '>'), ('[', ']')],
 7387                view,
 7388                cx,
 7389            );
 7390
 7391            view.move_right(&MoveRight, cx);
 7392            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7393            assert_selection_ranges(
 7394                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7395                vec![('<', '>'), ('[', ']')],
 7396                view,
 7397                cx,
 7398            );
 7399
 7400            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7401            assert_selection_ranges(
 7402                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7403                vec![('<', '>'), ('[', ']')],
 7404                view,
 7405                cx,
 7406            );
 7407
 7408            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7409            assert_selection_ranges(
 7410                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7411                vec![('<', '>'), ('[', ']')],
 7412                view,
 7413                cx,
 7414            );
 7415        });
 7416    }
 7417
 7418    #[gpui::test]
 7419    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7420        cx.set_global(Settings::test(cx));
 7421        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7422        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7423
 7424        view.update(cx, |view, cx| {
 7425            view.set_wrap_width(Some(140.), cx);
 7426            assert_eq!(
 7427                view.display_text(cx),
 7428                "use one::{\n    two::three::\n    four::five\n};"
 7429            );
 7430
 7431            view.change_selections(None, cx, |s| {
 7432                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7433            });
 7434
 7435            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7436            assert_eq!(
 7437                view.selections.display_ranges(cx),
 7438                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7439            );
 7440
 7441            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7442            assert_eq!(
 7443                view.selections.display_ranges(cx),
 7444                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7445            );
 7446
 7447            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7448            assert_eq!(
 7449                view.selections.display_ranges(cx),
 7450                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7451            );
 7452
 7453            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7454            assert_eq!(
 7455                view.selections.display_ranges(cx),
 7456                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7457            );
 7458
 7459            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7460            assert_eq!(
 7461                view.selections.display_ranges(cx),
 7462                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7463            );
 7464
 7465            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7466            assert_eq!(
 7467                view.selections.display_ranges(cx),
 7468                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7469            );
 7470        });
 7471    }
 7472
 7473    #[gpui::test]
 7474    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7475        cx.set_global(Settings::test(cx));
 7476        let (text, ranges) = marked_text_ranges("one [two three] four");
 7477        let buffer = MultiBuffer::build_simple(&text, cx);
 7478
 7479        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7480
 7481        editor.update(cx, |editor, cx| {
 7482            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
 7483            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7484            assert_eq!(editor.text(cx), " four");
 7485        });
 7486    }
 7487
 7488    #[gpui::test]
 7489    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7490        cx.set_global(Settings::test(cx));
 7491        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7492        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7493
 7494        view.update(cx, |view, cx| {
 7495            view.change_selections(None, cx, |s| {
 7496                s.select_display_ranges([
 7497                    // an empty selection - the preceding word fragment is deleted
 7498                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7499                    // characters selected - they are deleted
 7500                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7501                ])
 7502            });
 7503            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7504        });
 7505
 7506        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7507
 7508        view.update(cx, |view, cx| {
 7509            view.change_selections(None, cx, |s| {
 7510                s.select_display_ranges([
 7511                    // an empty selection - the following word fragment is deleted
 7512                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7513                    // characters selected - they are deleted
 7514                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7515                ])
 7516            });
 7517            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7518        });
 7519
 7520        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7521    }
 7522
 7523    #[gpui::test]
 7524    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7525        cx.set_global(Settings::test(cx));
 7526        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7527        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7528
 7529        view.update(cx, |view, cx| {
 7530            view.change_selections(None, cx, |s| {
 7531                s.select_display_ranges([
 7532                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7533                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7534                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7535                ])
 7536            });
 7537
 7538            view.newline(&Newline, cx);
 7539            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7540        });
 7541    }
 7542
 7543    #[gpui::test]
 7544    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7545        cx.set_global(Settings::test(cx));
 7546        let buffer = MultiBuffer::build_simple(
 7547            "
 7548                a
 7549                b(
 7550                    X
 7551                )
 7552                c(
 7553                    X
 7554                )
 7555            "
 7556            .unindent()
 7557            .as_str(),
 7558            cx,
 7559        );
 7560
 7561        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7562            let mut editor = build_editor(buffer.clone(), cx);
 7563            editor.change_selections(None, cx, |s| {
 7564                s.select_ranges([
 7565                    Point::new(2, 4)..Point::new(2, 5),
 7566                    Point::new(5, 4)..Point::new(5, 5),
 7567                ])
 7568            });
 7569            editor
 7570        });
 7571
 7572        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7573        buffer.update(cx, |buffer, cx| {
 7574            buffer.edit(
 7575                [
 7576                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7577                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7578                ],
 7579                cx,
 7580            );
 7581            assert_eq!(
 7582                buffer.read(cx).text(),
 7583                "
 7584                    a
 7585                    b()
 7586                    c()
 7587                "
 7588                .unindent()
 7589            );
 7590        });
 7591
 7592        editor.update(cx, |editor, cx| {
 7593            assert_eq!(
 7594                editor.selections.ranges(cx),
 7595                &[
 7596                    Point::new(1, 2)..Point::new(1, 2),
 7597                    Point::new(2, 2)..Point::new(2, 2),
 7598                ],
 7599            );
 7600
 7601            editor.newline(&Newline, cx);
 7602            assert_eq!(
 7603                editor.text(cx),
 7604                "
 7605                    a
 7606                    b(
 7607                    )
 7608                    c(
 7609                    )
 7610                "
 7611                .unindent()
 7612            );
 7613
 7614            // The selections are moved after the inserted newlines
 7615            assert_eq!(
 7616                editor.selections.ranges(cx),
 7617                &[
 7618                    Point::new(2, 0)..Point::new(2, 0),
 7619                    Point::new(4, 0)..Point::new(4, 0),
 7620                ],
 7621            );
 7622        });
 7623    }
 7624
 7625    #[gpui::test]
 7626    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7627        cx.set_global(Settings::test(cx));
 7628        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7629        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7630            let mut editor = build_editor(buffer.clone(), cx);
 7631            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 7632            editor
 7633        });
 7634
 7635        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7636        buffer.update(cx, |buffer, cx| {
 7637            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7638            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7639        });
 7640
 7641        editor.update(cx, |editor, cx| {
 7642            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 7643
 7644            editor.insert("Z", cx);
 7645            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7646
 7647            // The selections are moved after the inserted characters
 7648            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 7649        });
 7650    }
 7651
 7652    #[gpui::test]
 7653    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 7654        let mut cx = EditorTestContext::new(cx).await;
 7655
 7656        cx.set_state(indoc! {"
 7657              [one} [two}
 7658            three
 7659             four"});
 7660        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7661        cx.assert_editor_state(indoc! {"
 7662                [one} [two}
 7663            three
 7664             four"});
 7665
 7666        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7667        cx.assert_editor_state(indoc! {"
 7668            [one} [two}
 7669            three
 7670             four"});
 7671
 7672        // select across line ending
 7673        cx.set_state(indoc! {"
 7674            one two
 7675            t[hree
 7676            } four"});
 7677        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7678        cx.assert_editor_state(indoc! {"
 7679            one two
 7680                t[hree
 7681            } four"});
 7682
 7683        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7684        cx.assert_editor_state(indoc! {"
 7685            one two
 7686            t[hree
 7687            } four"});
 7688
 7689        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7690        cx.set_state(indoc! {"
 7691            one two
 7692            |three
 7693                four"});
 7694        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7695        cx.assert_editor_state(indoc! {"
 7696            one two
 7697                |three
 7698                four"});
 7699
 7700        cx.set_state(indoc! {"
 7701            one two
 7702            |    three
 7703             four"});
 7704        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7705        cx.assert_editor_state(indoc! {"
 7706            one two
 7707            |three
 7708             four"});
 7709    }
 7710
 7711    #[gpui::test]
 7712    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7713        cx.set_global(
 7714            Settings::test(cx)
 7715                .with_overrides(
 7716                    "TOML",
 7717                    LanguageOverride {
 7718                        tab_size: Some(2),
 7719                        ..Default::default()
 7720                    },
 7721                )
 7722                .with_overrides(
 7723                    "Rust",
 7724                    LanguageOverride {
 7725                        tab_size: Some(4),
 7726                        ..Default::default()
 7727                    },
 7728                ),
 7729        );
 7730        let toml_language = Arc::new(Language::new(
 7731            LanguageConfig {
 7732                name: "TOML".into(),
 7733                ..Default::default()
 7734            },
 7735            None,
 7736        ));
 7737        let rust_language = Arc::new(Language::new(
 7738            LanguageConfig {
 7739                name: "Rust".into(),
 7740                ..Default::default()
 7741            },
 7742            None,
 7743        ));
 7744
 7745        let toml_buffer = cx
 7746            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7747        let rust_buffer = cx.add_model(|cx| {
 7748            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7749        });
 7750        let multibuffer = cx.add_model(|cx| {
 7751            let mut multibuffer = MultiBuffer::new(0);
 7752            multibuffer.push_excerpts(
 7753                toml_buffer.clone(),
 7754                [ExcerptRange {
 7755                    context: Point::new(0, 0)..Point::new(2, 0),
 7756                    primary: None,
 7757                }],
 7758                cx,
 7759            );
 7760            multibuffer.push_excerpts(
 7761                rust_buffer.clone(),
 7762                [ExcerptRange {
 7763                    context: Point::new(0, 0)..Point::new(1, 0),
 7764                    primary: None,
 7765                }],
 7766                cx,
 7767            );
 7768            multibuffer
 7769        });
 7770
 7771        cx.add_window(Default::default(), |cx| {
 7772            let mut editor = build_editor(multibuffer, cx);
 7773
 7774            assert_eq!(
 7775                editor.text(cx),
 7776                indoc! {"
 7777                    a = 1
 7778                    b = 2
 7779
 7780                    const c: usize = 3;
 7781                "}
 7782            );
 7783
 7784            select_ranges(
 7785                &mut editor,
 7786                indoc! {"
 7787                    [a] = 1
 7788                    b = 2
 7789
 7790                    [const c:] usize = 3;
 7791                "},
 7792                cx,
 7793            );
 7794
 7795            editor.tab(&Tab, cx);
 7796            assert_text_with_selections(
 7797                &mut editor,
 7798                indoc! {"
 7799                      [a] = 1
 7800                    b = 2
 7801
 7802                        [const c:] usize = 3;
 7803                "},
 7804                cx,
 7805            );
 7806            editor.tab_prev(&TabPrev, cx);
 7807            assert_text_with_selections(
 7808                &mut editor,
 7809                indoc! {"
 7810                    [a] = 1
 7811                    b = 2
 7812
 7813                    [const c:] usize = 3;
 7814                "},
 7815                cx,
 7816            );
 7817
 7818            editor
 7819        });
 7820    }
 7821
 7822    #[gpui::test]
 7823    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 7824        let mut cx = EditorTestContext::new(cx).await;
 7825        // Basic backspace
 7826        cx.set_state(indoc! {"
 7827            on|e two three
 7828            fou[r} five six
 7829            seven {eight nine
 7830            ]ten"});
 7831        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7832        cx.assert_editor_state(indoc! {"
 7833            o|e two three
 7834            fou| five six
 7835            seven |ten"});
 7836
 7837        // Test backspace inside and around indents
 7838        cx.set_state(indoc! {"
 7839            zero
 7840                |one
 7841                    |two
 7842                | | |  three
 7843            |  |  four"});
 7844        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7845        cx.assert_editor_state(indoc! {"
 7846            zero
 7847            |one
 7848                |two
 7849            |  three|  four"});
 7850
 7851        // Test backspace with line_mode set to true
 7852        cx.update_editor(|e, _| e.selections.line_mode = true);
 7853        cx.set_state(indoc! {"
 7854            The |quick |brown
 7855            fox jumps over
 7856            the lazy dog
 7857            |The qu[ick b}rown"});
 7858        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7859        cx.assert_editor_state(indoc! {"
 7860            |fox jumps over
 7861            the lazy dog|"});
 7862    }
 7863
 7864    #[gpui::test]
 7865    async fn test_delete(cx: &mut gpui::TestAppContext) {
 7866        let mut cx = EditorTestContext::new(cx).await;
 7867
 7868        cx.set_state(indoc! {"
 7869            on|e two three
 7870            fou[r} five six
 7871            seven {eight nine
 7872            ]ten"});
 7873        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 7874        cx.assert_editor_state(indoc! {"
 7875            on| two three
 7876            fou| five six
 7877            seven |ten"});
 7878
 7879        // Test backspace with line_mode set to true
 7880        cx.update_editor(|e, _| e.selections.line_mode = true);
 7881        cx.set_state(indoc! {"
 7882            The |quick |brown
 7883            fox {jum]ps over
 7884            the lazy dog
 7885            |The qu[ick b}rown"});
 7886        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7887        cx.assert_editor_state("|the lazy dog|");
 7888    }
 7889
 7890    #[gpui::test]
 7891    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7892        cx.set_global(Settings::test(cx));
 7893        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7894        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7895        view.update(cx, |view, cx| {
 7896            view.change_selections(None, cx, |s| {
 7897                s.select_display_ranges([
 7898                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7899                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7900                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7901                ])
 7902            });
 7903            view.delete_line(&DeleteLine, cx);
 7904            assert_eq!(view.display_text(cx), "ghi");
 7905            assert_eq!(
 7906                view.selections.display_ranges(cx),
 7907                vec![
 7908                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7909                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7910                ]
 7911            );
 7912        });
 7913
 7914        cx.set_global(Settings::test(cx));
 7915        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7916        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7917        view.update(cx, |view, cx| {
 7918            view.change_selections(None, cx, |s| {
 7919                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 7920            });
 7921            view.delete_line(&DeleteLine, cx);
 7922            assert_eq!(view.display_text(cx), "ghi\n");
 7923            assert_eq!(
 7924                view.selections.display_ranges(cx),
 7925                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 7926            );
 7927        });
 7928    }
 7929
 7930    #[gpui::test]
 7931    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 7932        cx.set_global(Settings::test(cx));
 7933        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7934        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7935        view.update(cx, |view, cx| {
 7936            view.change_selections(None, cx, |s| {
 7937                s.select_display_ranges([
 7938                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 7939                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7940                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7941                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7942                ])
 7943            });
 7944            view.duplicate_line(&DuplicateLine, cx);
 7945            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 7946            assert_eq!(
 7947                view.selections.display_ranges(cx),
 7948                vec![
 7949                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7950                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7951                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7952                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 7953                ]
 7954            );
 7955        });
 7956
 7957        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7958        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7959        view.update(cx, |view, cx| {
 7960            view.change_selections(None, cx, |s| {
 7961                s.select_display_ranges([
 7962                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 7963                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 7964                ])
 7965            });
 7966            view.duplicate_line(&DuplicateLine, cx);
 7967            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 7968            assert_eq!(
 7969                view.selections.display_ranges(cx),
 7970                vec![
 7971                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 7972                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 7973                ]
 7974            );
 7975        });
 7976    }
 7977
 7978    #[gpui::test]
 7979    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 7980        cx.set_global(Settings::test(cx));
 7981        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 7982        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7983        view.update(cx, |view, cx| {
 7984            view.fold_ranges(
 7985                vec![
 7986                    Point::new(0, 2)..Point::new(1, 2),
 7987                    Point::new(2, 3)..Point::new(4, 1),
 7988                    Point::new(7, 0)..Point::new(8, 4),
 7989                ],
 7990                cx,
 7991            );
 7992            view.change_selections(None, cx, |s| {
 7993                s.select_display_ranges([
 7994                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7995                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 7996                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 7997                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 7998                ])
 7999            });
 8000            assert_eq!(
 8001                view.display_text(cx),
 8002                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8003            );
 8004
 8005            view.move_line_up(&MoveLineUp, cx);
 8006            assert_eq!(
 8007                view.display_text(cx),
 8008                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8009            );
 8010            assert_eq!(
 8011                view.selections.display_ranges(cx),
 8012                vec![
 8013                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8014                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8015                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8016                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8017                ]
 8018            );
 8019        });
 8020
 8021        view.update(cx, |view, cx| {
 8022            view.move_line_down(&MoveLineDown, cx);
 8023            assert_eq!(
 8024                view.display_text(cx),
 8025                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8026            );
 8027            assert_eq!(
 8028                view.selections.display_ranges(cx),
 8029                vec![
 8030                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8031                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8032                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8033                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8034                ]
 8035            );
 8036        });
 8037
 8038        view.update(cx, |view, cx| {
 8039            view.move_line_down(&MoveLineDown, cx);
 8040            assert_eq!(
 8041                view.display_text(cx),
 8042                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8043            );
 8044            assert_eq!(
 8045                view.selections.display_ranges(cx),
 8046                vec![
 8047                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8048                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8049                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8050                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8051                ]
 8052            );
 8053        });
 8054
 8055        view.update(cx, |view, cx| {
 8056            view.move_line_up(&MoveLineUp, cx);
 8057            assert_eq!(
 8058                view.display_text(cx),
 8059                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8060            );
 8061            assert_eq!(
 8062                view.selections.display_ranges(cx),
 8063                vec![
 8064                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8065                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8066                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8067                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8068                ]
 8069            );
 8070        });
 8071    }
 8072
 8073    #[gpui::test]
 8074    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8075        cx.set_global(Settings::test(cx));
 8076        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8077        let snapshot = buffer.read(cx).snapshot(cx);
 8078        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8079        editor.update(cx, |editor, cx| {
 8080            editor.insert_blocks(
 8081                [BlockProperties {
 8082                    position: snapshot.anchor_after(Point::new(2, 0)),
 8083                    disposition: BlockDisposition::Below,
 8084                    height: 1,
 8085                    render: Arc::new(|_| Empty::new().boxed()),
 8086                }],
 8087                cx,
 8088            );
 8089            editor.change_selections(None, cx, |s| {
 8090                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8091            });
 8092            editor.move_line_down(&MoveLineDown, cx);
 8093        });
 8094    }
 8095
 8096    #[gpui::test]
 8097    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8098        cx.set_global(Settings::test(cx));
 8099
 8100        cx.add_window(Default::default(), |cx| {
 8101            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8102
 8103            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8104            editor.transpose(&Default::default(), cx);
 8105            assert_eq!(editor.text(cx), "bac");
 8106            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8107
 8108            editor.transpose(&Default::default(), cx);
 8109            assert_eq!(editor.text(cx), "bca");
 8110            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8111
 8112            editor.transpose(&Default::default(), cx);
 8113            assert_eq!(editor.text(cx), "bac");
 8114            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8115
 8116            editor
 8117        })
 8118        .1;
 8119
 8120        cx.add_window(Default::default(), |cx| {
 8121            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8122
 8123            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8124            editor.transpose(&Default::default(), cx);
 8125            assert_eq!(editor.text(cx), "acb\nde");
 8126            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8127
 8128            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8129            editor.transpose(&Default::default(), cx);
 8130            assert_eq!(editor.text(cx), "acbd\ne");
 8131            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8132
 8133            editor.transpose(&Default::default(), cx);
 8134            assert_eq!(editor.text(cx), "acbde\n");
 8135            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8136
 8137            editor.transpose(&Default::default(), cx);
 8138            assert_eq!(editor.text(cx), "acbd\ne");
 8139            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8140
 8141            editor
 8142        })
 8143        .1;
 8144
 8145        cx.add_window(Default::default(), |cx| {
 8146            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8147
 8148            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8149            editor.transpose(&Default::default(), cx);
 8150            assert_eq!(editor.text(cx), "bacd\ne");
 8151            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8152
 8153            editor.transpose(&Default::default(), cx);
 8154            assert_eq!(editor.text(cx), "bcade\n");
 8155            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8156
 8157            editor.transpose(&Default::default(), cx);
 8158            assert_eq!(editor.text(cx), "bcda\ne");
 8159            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8160
 8161            editor.transpose(&Default::default(), cx);
 8162            assert_eq!(editor.text(cx), "bcade\n");
 8163            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8164
 8165            editor.transpose(&Default::default(), cx);
 8166            assert_eq!(editor.text(cx), "bcaed\n");
 8167            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8168
 8169            editor
 8170        })
 8171        .1;
 8172
 8173        cx.add_window(Default::default(), |cx| {
 8174            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8175
 8176            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8177            editor.transpose(&Default::default(), cx);
 8178            assert_eq!(editor.text(cx), "🏀🍐✋");
 8179            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8180
 8181            editor.transpose(&Default::default(), cx);
 8182            assert_eq!(editor.text(cx), "🏀✋🍐");
 8183            assert_eq!(editor.selections.ranges(cx), [11..11]);
 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
 8190        })
 8191        .1;
 8192    }
 8193
 8194    #[gpui::test]
 8195    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8196        let mut cx = EditorTestContext::new(cx).await;
 8197
 8198        cx.set_state("[one✅ }two [three }four [five }six ");
 8199        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8200        cx.assert_editor_state("|two |four |six ");
 8201
 8202        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8203        cx.set_state("two |four |six |");
 8204        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8205        cx.assert_editor_state("two one✅ |four three |six five |");
 8206
 8207        // Paste again but with only two cursors. Since the number of cursors doesn't
 8208        // match the number of slices in the clipboard, the entire clipboard text
 8209        // is pasted at each cursor.
 8210        cx.set_state("|two one✅ four three six five |");
 8211        cx.update_editor(|e, cx| {
 8212            e.handle_input(&Input("( ".into()), cx);
 8213            e.paste(&Paste, cx);
 8214            e.handle_input(&Input(") ".into()), cx);
 8215        });
 8216        cx.assert_editor_state(indoc! {"
 8217            ( one✅ 
 8218            three 
 8219            five ) |two one✅ four three six five ( one✅ 
 8220            three 
 8221            five ) |"});
 8222
 8223        // Cut with three selections, one of which is full-line.
 8224        cx.set_state(indoc! {"
 8225            1[2}3
 8226            4|567
 8227            [8}9"});
 8228        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8229        cx.assert_editor_state(indoc! {"
 8230            1|3
 8231            |9"});
 8232
 8233        // Paste with three selections, noticing how the copied selection that was full-line
 8234        // gets inserted before the second cursor.
 8235        cx.set_state(indoc! {"
 8236            1|3
 8237            9|
 8238            [o}ne"});
 8239        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8240        cx.assert_editor_state(indoc! {"
 8241            12|3
 8242            4567
 8243            9|
 8244            8|ne"});
 8245
 8246        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8247        cx.set_state(indoc! {"
 8248            The quick brown
 8249            fox ju|mps over
 8250            the lazy dog"});
 8251        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8252        cx.assert_clipboard_content(Some("fox jumps over\n"));
 8253
 8254        // Paste with three selections, noticing how the copied full-line selection is inserted
 8255        // before the empty selections but replaces the selection that is non-empty.
 8256        cx.set_state(indoc! {"
 8257            T|he quick brown
 8258            [fo}x jumps over
 8259            t|he lazy dog"});
 8260        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8261        cx.assert_editor_state(indoc! {"
 8262            fox jumps over
 8263            T|he quick brown
 8264            fox jumps over
 8265            |x jumps over
 8266            fox jumps over
 8267            t|he lazy dog"});
 8268    }
 8269
 8270    #[gpui::test]
 8271    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8272        cx.set_global(Settings::test(cx));
 8273        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8274        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8275        view.update(cx, |view, cx| {
 8276            view.select_all(&SelectAll, cx);
 8277            assert_eq!(
 8278                view.selections.display_ranges(cx),
 8279                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8280            );
 8281        });
 8282    }
 8283
 8284    #[gpui::test]
 8285    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8286        cx.set_global(Settings::test(cx));
 8287        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8288        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8289        view.update(cx, |view, cx| {
 8290            view.change_selections(None, cx, |s| {
 8291                s.select_display_ranges([
 8292                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8293                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8294                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8295                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8296                ])
 8297            });
 8298            view.select_line(&SelectLine, cx);
 8299            assert_eq!(
 8300                view.selections.display_ranges(cx),
 8301                vec![
 8302                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8303                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8304                ]
 8305            );
 8306        });
 8307
 8308        view.update(cx, |view, cx| {
 8309            view.select_line(&SelectLine, cx);
 8310            assert_eq!(
 8311                view.selections.display_ranges(cx),
 8312                vec![
 8313                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8314                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8315                ]
 8316            );
 8317        });
 8318
 8319        view.update(cx, |view, cx| {
 8320            view.select_line(&SelectLine, cx);
 8321            assert_eq!(
 8322                view.selections.display_ranges(cx),
 8323                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8324            );
 8325        });
 8326    }
 8327
 8328    #[gpui::test]
 8329    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8330        cx.set_global(Settings::test(cx));
 8331        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8332        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8333        view.update(cx, |view, cx| {
 8334            view.fold_ranges(
 8335                vec![
 8336                    Point::new(0, 2)..Point::new(1, 2),
 8337                    Point::new(2, 3)..Point::new(4, 1),
 8338                    Point::new(7, 0)..Point::new(8, 4),
 8339                ],
 8340                cx,
 8341            );
 8342            view.change_selections(None, cx, |s| {
 8343                s.select_display_ranges([
 8344                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8345                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8346                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8347                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8348                ])
 8349            });
 8350            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8351        });
 8352
 8353        view.update(cx, |view, cx| {
 8354            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8355            assert_eq!(
 8356                view.display_text(cx),
 8357                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8358            );
 8359            assert_eq!(
 8360                view.selections.display_ranges(cx),
 8361                [
 8362                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8363                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8364                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8365                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8366                ]
 8367            );
 8368        });
 8369
 8370        view.update(cx, |view, cx| {
 8371            view.change_selections(None, cx, |s| {
 8372                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 8373            });
 8374            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8375            assert_eq!(
 8376                view.display_text(cx),
 8377                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8378            );
 8379            assert_eq!(
 8380                view.selections.display_ranges(cx),
 8381                [
 8382                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8383                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8384                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8385                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8386                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8387                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8388                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8389                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8390                ]
 8391            );
 8392        });
 8393    }
 8394
 8395    #[gpui::test]
 8396    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8397        cx.set_global(Settings::test(cx));
 8398        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8399        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8400
 8401        view.update(cx, |view, cx| {
 8402            view.change_selections(None, cx, |s| {
 8403                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 8404            });
 8405        });
 8406        view.update(cx, |view, cx| {
 8407            view.add_selection_above(&AddSelectionAbove, cx);
 8408            assert_eq!(
 8409                view.selections.display_ranges(cx),
 8410                vec![
 8411                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8412                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8413                ]
 8414            );
 8415        });
 8416
 8417        view.update(cx, |view, cx| {
 8418            view.add_selection_above(&AddSelectionAbove, cx);
 8419            assert_eq!(
 8420                view.selections.display_ranges(cx),
 8421                vec![
 8422                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8423                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8424                ]
 8425            );
 8426        });
 8427
 8428        view.update(cx, |view, cx| {
 8429            view.add_selection_below(&AddSelectionBelow, cx);
 8430            assert_eq!(
 8431                view.selections.display_ranges(cx),
 8432                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8433            );
 8434
 8435            view.undo_selection(&UndoSelection, cx);
 8436            assert_eq!(
 8437                view.selections.display_ranges(cx),
 8438                vec![
 8439                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8440                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8441                ]
 8442            );
 8443
 8444            view.redo_selection(&RedoSelection, cx);
 8445            assert_eq!(
 8446                view.selections.display_ranges(cx),
 8447                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8448            );
 8449        });
 8450
 8451        view.update(cx, |view, cx| {
 8452            view.add_selection_below(&AddSelectionBelow, cx);
 8453            assert_eq!(
 8454                view.selections.display_ranges(cx),
 8455                vec![
 8456                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8457                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8458                ]
 8459            );
 8460        });
 8461
 8462        view.update(cx, |view, cx| {
 8463            view.add_selection_below(&AddSelectionBelow, cx);
 8464            assert_eq!(
 8465                view.selections.display_ranges(cx),
 8466                vec![
 8467                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8468                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8469                ]
 8470            );
 8471        });
 8472
 8473        view.update(cx, |view, cx| {
 8474            view.change_selections(None, cx, |s| {
 8475                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 8476            });
 8477        });
 8478        view.update(cx, |view, cx| {
 8479            view.add_selection_below(&AddSelectionBelow, cx);
 8480            assert_eq!(
 8481                view.selections.display_ranges(cx),
 8482                vec![
 8483                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8484                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8485                ]
 8486            );
 8487        });
 8488
 8489        view.update(cx, |view, cx| {
 8490            view.add_selection_below(&AddSelectionBelow, cx);
 8491            assert_eq!(
 8492                view.selections.display_ranges(cx),
 8493                vec![
 8494                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8495                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8496                ]
 8497            );
 8498        });
 8499
 8500        view.update(cx, |view, cx| {
 8501            view.add_selection_above(&AddSelectionAbove, cx);
 8502            assert_eq!(
 8503                view.selections.display_ranges(cx),
 8504                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8505            );
 8506        });
 8507
 8508        view.update(cx, |view, cx| {
 8509            view.add_selection_above(&AddSelectionAbove, cx);
 8510            assert_eq!(
 8511                view.selections.display_ranges(cx),
 8512                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8513            );
 8514        });
 8515
 8516        view.update(cx, |view, cx| {
 8517            view.change_selections(None, cx, |s| {
 8518                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 8519            });
 8520            view.add_selection_below(&AddSelectionBelow, cx);
 8521            assert_eq!(
 8522                view.selections.display_ranges(cx),
 8523                vec![
 8524                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8525                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8526                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8527                ]
 8528            );
 8529        });
 8530
 8531        view.update(cx, |view, cx| {
 8532            view.add_selection_below(&AddSelectionBelow, cx);
 8533            assert_eq!(
 8534                view.selections.display_ranges(cx),
 8535                vec![
 8536                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8537                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8538                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8539                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8540                ]
 8541            );
 8542        });
 8543
 8544        view.update(cx, |view, cx| {
 8545            view.add_selection_above(&AddSelectionAbove, cx);
 8546            assert_eq!(
 8547                view.selections.display_ranges(cx),
 8548                vec![
 8549                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8550                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8551                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8552                ]
 8553            );
 8554        });
 8555
 8556        view.update(cx, |view, cx| {
 8557            view.change_selections(None, cx, |s| {
 8558                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 8559            });
 8560        });
 8561        view.update(cx, |view, cx| {
 8562            view.add_selection_above(&AddSelectionAbove, cx);
 8563            assert_eq!(
 8564                view.selections.display_ranges(cx),
 8565                vec![
 8566                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8567                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8568                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8569                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8570                ]
 8571            );
 8572        });
 8573
 8574        view.update(cx, |view, cx| {
 8575            view.add_selection_below(&AddSelectionBelow, cx);
 8576            assert_eq!(
 8577                view.selections.display_ranges(cx),
 8578                vec![
 8579                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8580                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8581                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8582                ]
 8583            );
 8584        });
 8585    }
 8586
 8587    #[gpui::test]
 8588    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8589        cx.set_global(Settings::test(cx));
 8590
 8591        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8592        let buffer = MultiBuffer::build_simple(&text, cx);
 8593        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8594
 8595        view.update(cx, |view, cx| {
 8596            view.change_selections(None, cx, |s| {
 8597                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 8598            });
 8599            view.select_next(
 8600                &SelectNext {
 8601                    replace_newest: false,
 8602                },
 8603                cx,
 8604            );
 8605            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8606
 8607            view.select_next(
 8608                &SelectNext {
 8609                    replace_newest: false,
 8610                },
 8611                cx,
 8612            );
 8613            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8614
 8615            view.undo_selection(&UndoSelection, cx);
 8616            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8617
 8618            view.redo_selection(&RedoSelection, cx);
 8619            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8620
 8621            view.select_next(
 8622                &SelectNext {
 8623                    replace_newest: false,
 8624                },
 8625                cx,
 8626            );
 8627            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 8628
 8629            view.select_next(
 8630                &SelectNext {
 8631                    replace_newest: false,
 8632                },
 8633                cx,
 8634            );
 8635            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 8636        });
 8637    }
 8638
 8639    #[gpui::test]
 8640    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8641        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8642        let language = Arc::new(Language::new(
 8643            LanguageConfig::default(),
 8644            Some(tree_sitter_rust::language()),
 8645        ));
 8646
 8647        let text = r#"
 8648            use mod1::mod2::{mod3, mod4};
 8649
 8650            fn fn_1(param1: bool, param2: &str) {
 8651                let var1 = "text";
 8652            }
 8653        "#
 8654        .unindent();
 8655
 8656        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8657        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8658        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8659        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8660            .await;
 8661
 8662        view.update(cx, |view, cx| {
 8663            view.change_selections(None, cx, |s| {
 8664                s.select_display_ranges([
 8665                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8666                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8667                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8668                ]);
 8669            });
 8670            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8671        });
 8672        assert_eq!(
 8673            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 8674            &[
 8675                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8676                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8677                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8678            ]
 8679        );
 8680
 8681        view.update(cx, |view, cx| {
 8682            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8683        });
 8684        assert_eq!(
 8685            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8686            &[
 8687                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8688                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8689            ]
 8690        );
 8691
 8692        view.update(cx, |view, cx| {
 8693            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8694        });
 8695        assert_eq!(
 8696            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8697            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8698        );
 8699
 8700        // Trying to expand the selected syntax node one more time has no effect.
 8701        view.update(cx, |view, cx| {
 8702            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8703        });
 8704        assert_eq!(
 8705            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8706            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8707        );
 8708
 8709        view.update(cx, |view, cx| {
 8710            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8711        });
 8712        assert_eq!(
 8713            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8714            &[
 8715                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8716                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8717            ]
 8718        );
 8719
 8720        view.update(cx, |view, cx| {
 8721            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8722        });
 8723        assert_eq!(
 8724            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8725            &[
 8726                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8727                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8728                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8729            ]
 8730        );
 8731
 8732        view.update(cx, |view, cx| {
 8733            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8734        });
 8735        assert_eq!(
 8736            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8737            &[
 8738                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8739                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8740                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8741            ]
 8742        );
 8743
 8744        // Trying to shrink the selected syntax node one more time has no effect.
 8745        view.update(cx, |view, cx| {
 8746            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8747        });
 8748        assert_eq!(
 8749            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8750            &[
 8751                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8752                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8753                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8754            ]
 8755        );
 8756
 8757        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8758        // a fold.
 8759        view.update(cx, |view, cx| {
 8760            view.fold_ranges(
 8761                vec![
 8762                    Point::new(0, 21)..Point::new(0, 24),
 8763                    Point::new(3, 20)..Point::new(3, 22),
 8764                ],
 8765                cx,
 8766            );
 8767            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8768        });
 8769        assert_eq!(
 8770            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8771            &[
 8772                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8773                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8774                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8775            ]
 8776        );
 8777    }
 8778
 8779    #[gpui::test]
 8780    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8781        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8782        let language = Arc::new(
 8783            Language::new(
 8784                LanguageConfig {
 8785                    brackets: vec![
 8786                        BracketPair {
 8787                            start: "{".to_string(),
 8788                            end: "}".to_string(),
 8789                            close: false,
 8790                            newline: true,
 8791                        },
 8792                        BracketPair {
 8793                            start: "(".to_string(),
 8794                            end: ")".to_string(),
 8795                            close: false,
 8796                            newline: true,
 8797                        },
 8798                    ],
 8799                    ..Default::default()
 8800                },
 8801                Some(tree_sitter_rust::language()),
 8802            )
 8803            .with_indents_query(
 8804                r#"
 8805                (_ "(" ")" @end) @indent
 8806                (_ "{" "}" @end) @indent
 8807                "#,
 8808            )
 8809            .unwrap(),
 8810        );
 8811
 8812        let text = "fn a() {}";
 8813
 8814        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8815        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8816        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8817        editor
 8818            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8819            .await;
 8820
 8821        editor.update(cx, |editor, cx| {
 8822            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 8823            editor.newline(&Newline, cx);
 8824            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8825            assert_eq!(
 8826                editor.selections.ranges(cx),
 8827                &[
 8828                    Point::new(1, 4)..Point::new(1, 4),
 8829                    Point::new(3, 4)..Point::new(3, 4),
 8830                    Point::new(5, 0)..Point::new(5, 0)
 8831                ]
 8832            );
 8833        });
 8834    }
 8835
 8836    #[gpui::test]
 8837    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8838        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8839        let language = Arc::new(Language::new(
 8840            LanguageConfig {
 8841                brackets: vec![
 8842                    BracketPair {
 8843                        start: "{".to_string(),
 8844                        end: "}".to_string(),
 8845                        close: true,
 8846                        newline: true,
 8847                    },
 8848                    BracketPair {
 8849                        start: "/*".to_string(),
 8850                        end: " */".to_string(),
 8851                        close: true,
 8852                        newline: true,
 8853                    },
 8854                ],
 8855                autoclose_before: "})]".to_string(),
 8856                ..Default::default()
 8857            },
 8858            Some(tree_sitter_rust::language()),
 8859        ));
 8860
 8861        let text = r#"
 8862            a
 8863
 8864            /
 8865
 8866        "#
 8867        .unindent();
 8868
 8869        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8870        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8871        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8872        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8873            .await;
 8874
 8875        view.update(cx, |view, cx| {
 8876            view.change_selections(None, cx, |s| {
 8877                s.select_display_ranges([
 8878                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8879                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8880                ])
 8881            });
 8882
 8883            view.handle_input(&Input("{".to_string()), cx);
 8884            view.handle_input(&Input("{".to_string()), cx);
 8885            view.handle_input(&Input("{".to_string()), cx);
 8886            assert_eq!(
 8887                view.text(cx),
 8888                "
 8889                {{{}}}
 8890                {{{}}}
 8891                /
 8892
 8893                "
 8894                .unindent()
 8895            );
 8896
 8897            view.move_right(&MoveRight, cx);
 8898            view.handle_input(&Input("}".to_string()), cx);
 8899            view.handle_input(&Input("}".to_string()), cx);
 8900            view.handle_input(&Input("}".to_string()), cx);
 8901            assert_eq!(
 8902                view.text(cx),
 8903                "
 8904                {{{}}}}
 8905                {{{}}}}
 8906                /
 8907
 8908                "
 8909                .unindent()
 8910            );
 8911
 8912            view.undo(&Undo, cx);
 8913            view.handle_input(&Input("/".to_string()), cx);
 8914            view.handle_input(&Input("*".to_string()), cx);
 8915            assert_eq!(
 8916                view.text(cx),
 8917                "
 8918                /* */
 8919                /* */
 8920                /
 8921
 8922                "
 8923                .unindent()
 8924            );
 8925
 8926            view.undo(&Undo, cx);
 8927            view.change_selections(None, cx, |s| {
 8928                s.select_display_ranges([
 8929                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8930                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8931                ])
 8932            });
 8933            view.handle_input(&Input("*".to_string()), cx);
 8934            assert_eq!(
 8935                view.text(cx),
 8936                "
 8937                a
 8938
 8939                /*
 8940                *
 8941                "
 8942                .unindent()
 8943            );
 8944
 8945            // Don't autoclose if the next character isn't whitespace and isn't
 8946            // listed in the language's "autoclose_before" section.
 8947            view.finalize_last_transaction(cx);
 8948            view.change_selections(None, cx, |s| {
 8949                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 8950            });
 8951            view.handle_input(&Input("{".to_string()), cx);
 8952            assert_eq!(
 8953                view.text(cx),
 8954                "
 8955                {a
 8956
 8957                /*
 8958                *
 8959                "
 8960                .unindent()
 8961            );
 8962
 8963            view.undo(&Undo, cx);
 8964            view.change_selections(None, cx, |s| {
 8965                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 8966            });
 8967            view.handle_input(&Input("{".to_string()), cx);
 8968            assert_eq!(
 8969                view.text(cx),
 8970                "
 8971                {a}
 8972
 8973                /*
 8974                *
 8975                "
 8976                .unindent()
 8977            );
 8978            assert_eq!(
 8979                view.selections.display_ranges(cx),
 8980                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8981            );
 8982        });
 8983    }
 8984
 8985    #[gpui::test]
 8986    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 8987        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8988
 8989        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 8990            a.| b
 8991            a.| b
 8992            a.| b"});
 8993        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 8994        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8995
 8996        editor.update(cx, |editor, cx| {
 8997            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 8998
 8999            editor
 9000                .insert_snippet(&insertion_ranges, snippet, cx)
 9001                .unwrap();
 9002
 9003            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 9004                let range_markers = ('<', '>');
 9005                let (expected_text, mut selection_ranges_lookup) =
 9006                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 9007                let selection_ranges = selection_ranges_lookup
 9008                    .remove(&range_markers.into())
 9009                    .unwrap();
 9010                assert_eq!(editor.text(cx), expected_text);
 9011                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9012            }
 9013            assert(
 9014                editor,
 9015                cx,
 9016                indoc! {"
 9017                    a.f(<one>, two, <three>) b
 9018                    a.f(<one>, two, <three>) b
 9019                    a.f(<one>, two, <three>) b"},
 9020            );
 9021
 9022            // Can't move earlier than the first tab stop
 9023            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9024            assert(
 9025                editor,
 9026                cx,
 9027                indoc! {"
 9028                    a.f(<one>, two, <three>) b
 9029                    a.f(<one>, two, <three>) b
 9030                    a.f(<one>, two, <three>) b"},
 9031            );
 9032
 9033            assert!(editor.move_to_next_snippet_tabstop(cx));
 9034            assert(
 9035                editor,
 9036                cx,
 9037                indoc! {"
 9038                    a.f(one, <two>, three) b
 9039                    a.f(one, <two>, three) b
 9040                    a.f(one, <two>, three) b"},
 9041            );
 9042
 9043            editor.move_to_prev_snippet_tabstop(cx);
 9044            assert(
 9045                editor,
 9046                cx,
 9047                indoc! {"
 9048                    a.f(<one>, two, <three>) b
 9049                    a.f(<one>, two, <three>) b
 9050                    a.f(<one>, two, <three>) b"},
 9051            );
 9052
 9053            assert!(editor.move_to_next_snippet_tabstop(cx));
 9054            assert(
 9055                editor,
 9056                cx,
 9057                indoc! {"
 9058                    a.f(one, <two>, three) b
 9059                    a.f(one, <two>, three) b
 9060                    a.f(one, <two>, three) b"},
 9061            );
 9062            assert!(editor.move_to_next_snippet_tabstop(cx));
 9063            assert(
 9064                editor,
 9065                cx,
 9066                indoc! {"
 9067                    a.f(one, two, three)<> b
 9068                    a.f(one, two, three)<> b
 9069                    a.f(one, two, three)<> b"},
 9070            );
 9071
 9072            // As soon as the last tab stop is reached, snippet state is gone
 9073            editor.move_to_prev_snippet_tabstop(cx);
 9074            assert(
 9075                editor,
 9076                cx,
 9077                indoc! {"
 9078                    a.f(one, two, three)<> b
 9079                    a.f(one, two, three)<> b
 9080                    a.f(one, two, three)<> b"},
 9081            );
 9082        });
 9083    }
 9084
 9085    #[gpui::test]
 9086    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9087        cx.foreground().forbid_parking();
 9088        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9089
 9090        let mut language = Language::new(
 9091            LanguageConfig {
 9092                name: "Rust".into(),
 9093                path_suffixes: vec!["rs".to_string()],
 9094                ..Default::default()
 9095            },
 9096            Some(tree_sitter_rust::language()),
 9097        );
 9098        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9099            capabilities: lsp::ServerCapabilities {
 9100                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9101                ..Default::default()
 9102            },
 9103            ..Default::default()
 9104        });
 9105
 9106        let fs = FakeFs::new(cx.background().clone());
 9107        fs.insert_file("/file.rs", Default::default()).await;
 9108
 9109        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9110        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9111        let buffer = project
 9112            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9113            .await
 9114            .unwrap();
 9115
 9116        cx.foreground().start_waiting();
 9117        let fake_server = fake_servers.next().await.unwrap();
 9118
 9119        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9120        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9121        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9122        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9123
 9124        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9125        fake_server
 9126            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9127                assert_eq!(
 9128                    params.text_document.uri,
 9129                    lsp::Url::from_file_path("/file.rs").unwrap()
 9130                );
 9131                assert_eq!(params.options.tab_size, 4);
 9132                Ok(Some(vec![lsp::TextEdit::new(
 9133                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9134                    ", ".to_string(),
 9135                )]))
 9136            })
 9137            .next()
 9138            .await;
 9139        cx.foreground().start_waiting();
 9140        save.await.unwrap();
 9141        assert_eq!(
 9142            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9143            "one, two\nthree\n"
 9144        );
 9145        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9146
 9147        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9148        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9149
 9150        // Ensure we can still save even if formatting hangs.
 9151        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9152            assert_eq!(
 9153                params.text_document.uri,
 9154                lsp::Url::from_file_path("/file.rs").unwrap()
 9155            );
 9156            futures::future::pending::<()>().await;
 9157            unreachable!()
 9158        });
 9159        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9160        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9161        cx.foreground().start_waiting();
 9162        save.await.unwrap();
 9163        assert_eq!(
 9164            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9165            "one\ntwo\nthree\n"
 9166        );
 9167        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9168
 9169        // Set rust language override and assert overriden tabsize is sent to language server
 9170        cx.update(|cx| {
 9171            cx.update_global::<Settings, _, _>(|settings, _| {
 9172                settings.language_overrides.insert(
 9173                    "Rust".into(),
 9174                    LanguageOverride {
 9175                        tab_size: Some(8),
 9176                        ..Default::default()
 9177                    },
 9178                );
 9179            })
 9180        });
 9181
 9182        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9183        fake_server
 9184            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9185                assert_eq!(
 9186                    params.text_document.uri,
 9187                    lsp::Url::from_file_path("/file.rs").unwrap()
 9188                );
 9189                assert_eq!(params.options.tab_size, 8);
 9190                Ok(Some(vec![]))
 9191            })
 9192            .next()
 9193            .await;
 9194        cx.foreground().start_waiting();
 9195        save.await.unwrap();
 9196    }
 9197
 9198    #[gpui::test]
 9199    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
 9200        cx.foreground().forbid_parking();
 9201        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9202
 9203        let mut language = Language::new(
 9204            LanguageConfig {
 9205                name: "Rust".into(),
 9206                path_suffixes: vec!["rs".to_string()],
 9207                ..Default::default()
 9208            },
 9209            Some(tree_sitter_rust::language()),
 9210        );
 9211        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9212            capabilities: lsp::ServerCapabilities {
 9213                document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
 9214                ..Default::default()
 9215            },
 9216            ..Default::default()
 9217        });
 9218
 9219        let fs = FakeFs::new(cx.background().clone());
 9220        fs.insert_file("/file.rs", Default::default()).await;
 9221
 9222        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9223        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9224        let buffer = project
 9225            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9226            .await
 9227            .unwrap();
 9228
 9229        cx.foreground().start_waiting();
 9230        let fake_server = fake_servers.next().await.unwrap();
 9231
 9232        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9233        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9234        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9235        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9236
 9237        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9238        fake_server
 9239            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9240                assert_eq!(
 9241                    params.text_document.uri,
 9242                    lsp::Url::from_file_path("/file.rs").unwrap()
 9243                );
 9244                assert_eq!(params.options.tab_size, 4);
 9245                Ok(Some(vec![lsp::TextEdit::new(
 9246                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9247                    ", ".to_string(),
 9248                )]))
 9249            })
 9250            .next()
 9251            .await;
 9252        cx.foreground().start_waiting();
 9253        save.await.unwrap();
 9254        assert_eq!(
 9255            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9256            "one, two\nthree\n"
 9257        );
 9258        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9259
 9260        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9261        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9262
 9263        // Ensure we can still save even if formatting hangs.
 9264        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
 9265            move |params, _| async move {
 9266                assert_eq!(
 9267                    params.text_document.uri,
 9268                    lsp::Url::from_file_path("/file.rs").unwrap()
 9269                );
 9270                futures::future::pending::<()>().await;
 9271                unreachable!()
 9272            },
 9273        );
 9274        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9275        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9276        cx.foreground().start_waiting();
 9277        save.await.unwrap();
 9278        assert_eq!(
 9279            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9280            "one\ntwo\nthree\n"
 9281        );
 9282        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9283
 9284        // Set rust language override and assert overriden tabsize is sent to language server
 9285        cx.update(|cx| {
 9286            cx.update_global::<Settings, _, _>(|settings, _| {
 9287                settings.language_overrides.insert(
 9288                    "Rust".into(),
 9289                    LanguageOverride {
 9290                        tab_size: Some(8),
 9291                        ..Default::default()
 9292                    },
 9293                );
 9294            })
 9295        });
 9296
 9297        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9298        fake_server
 9299            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9300                assert_eq!(
 9301                    params.text_document.uri,
 9302                    lsp::Url::from_file_path("/file.rs").unwrap()
 9303                );
 9304                assert_eq!(params.options.tab_size, 8);
 9305                Ok(Some(vec![]))
 9306            })
 9307            .next()
 9308            .await;
 9309        cx.foreground().start_waiting();
 9310        save.await.unwrap();
 9311    }
 9312
 9313    #[gpui::test]
 9314    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9315        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9316
 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}