editor.rs

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