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.clone(),
 5184            None => return None,
 5185        };
 5186
 5187        Some(self.perform_format(project, cx))
 5188    }
 5189
 5190    fn perform_format(
 5191        &mut self,
 5192        project: ModelHandle<Project>,
 5193        cx: &mut ViewContext<'_, Self>,
 5194    ) -> Task<Result<()>> {
 5195        let buffer = self.buffer().clone();
 5196        let buffers = buffer.read(cx).all_buffers();
 5197
 5198        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
 5199        let format = project.update(cx, |project, cx| {
 5200            project.format(buffers, true, FormatTrigger::Manual, cx)
 5201        });
 5202
 5203        cx.spawn(|_, mut cx| async move {
 5204            let transaction = futures::select_biased! {
 5205                _ = timeout => {
 5206                    log::warn!("timed out waiting for formatting");
 5207                    None
 5208                }
 5209                transaction = format.log_err().fuse() => transaction,
 5210            };
 5211
 5212            buffer.update(&mut cx, |buffer, cx| {
 5213                if let Some(transaction) = transaction {
 5214                    if !buffer.is_singleton() {
 5215                        buffer.push_transaction(&transaction.0);
 5216                    }
 5217                }
 5218
 5219                cx.notify();
 5220            });
 5221
 5222            Ok(())
 5223        })
 5224    }
 5225
 5226    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 5227        if let Some(project) = self.project.clone() {
 5228            self.buffer.update(cx, |multi_buffer, cx| {
 5229                project.update(cx, |project, cx| {
 5230                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 5231                });
 5232            })
 5233        }
 5234    }
 5235
 5236    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 5237        cx.show_character_palette();
 5238    }
 5239
 5240    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 5241        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 5242            let buffer = self.buffer.read(cx).snapshot(cx);
 5243            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 5244            let is_valid = buffer
 5245                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 5246                .any(|entry| {
 5247                    entry.diagnostic.is_primary
 5248                        && !entry.range.is_empty()
 5249                        && entry.range.start == primary_range_start
 5250                        && entry.diagnostic.message == active_diagnostics.primary_message
 5251                });
 5252
 5253            if is_valid != active_diagnostics.is_valid {
 5254                active_diagnostics.is_valid = is_valid;
 5255                let mut new_styles = HashMap::default();
 5256                for (block_id, diagnostic) in &active_diagnostics.blocks {
 5257                    new_styles.insert(
 5258                        *block_id,
 5259                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 5260                    );
 5261                }
 5262                self.display_map
 5263                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 5264            }
 5265        }
 5266    }
 5267
 5268    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 5269        self.dismiss_diagnostics(cx);
 5270        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 5271            let buffer = self.buffer.read(cx).snapshot(cx);
 5272
 5273            let mut primary_range = None;
 5274            let mut primary_message = None;
 5275            let mut group_end = Point::zero();
 5276            let diagnostic_group = buffer
 5277                .diagnostic_group::<Point>(group_id)
 5278                .map(|entry| {
 5279                    if entry.range.end > group_end {
 5280                        group_end = entry.range.end;
 5281                    }
 5282                    if entry.diagnostic.is_primary {
 5283                        primary_range = Some(entry.range.clone());
 5284                        primary_message = Some(entry.diagnostic.message.clone());
 5285                    }
 5286                    entry
 5287                })
 5288                .collect::<Vec<_>>();
 5289            let primary_range = primary_range?;
 5290            let primary_message = primary_message?;
 5291            let primary_range =
 5292                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 5293
 5294            let blocks = display_map
 5295                .insert_blocks(
 5296                    diagnostic_group.iter().map(|entry| {
 5297                        let diagnostic = entry.diagnostic.clone();
 5298                        let message_height = diagnostic.message.lines().count() as u8;
 5299                        BlockProperties {
 5300                            style: BlockStyle::Fixed,
 5301                            position: buffer.anchor_after(entry.range.start),
 5302                            height: message_height,
 5303                            render: diagnostic_block_renderer(diagnostic, true),
 5304                            disposition: BlockDisposition::Below,
 5305                        }
 5306                    }),
 5307                    cx,
 5308                )
 5309                .into_iter()
 5310                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 5311                .collect();
 5312
 5313            Some(ActiveDiagnosticGroup {
 5314                primary_range,
 5315                primary_message,
 5316                blocks,
 5317                is_valid: true,
 5318            })
 5319        });
 5320        self.active_diagnostics.is_some()
 5321    }
 5322
 5323    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 5324        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 5325            self.display_map.update(cx, |display_map, cx| {
 5326                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 5327            });
 5328            cx.notify();
 5329        }
 5330    }
 5331
 5332    pub fn set_selections_from_remote(
 5333        &mut self,
 5334        selections: Vec<Selection<Anchor>>,
 5335        cx: &mut ViewContext<Self>,
 5336    ) {
 5337        let old_cursor_position = self.selections.newest_anchor().head();
 5338        self.selections.change_with(cx, |s| {
 5339            s.select_anchors(selections);
 5340        });
 5341        self.selections_did_change(false, &old_cursor_position, cx);
 5342    }
 5343
 5344    fn push_to_selection_history(&mut self) {
 5345        self.selection_history.push(SelectionHistoryEntry {
 5346            selections: self.selections.disjoint_anchors(),
 5347            select_next_state: self.select_next_state.clone(),
 5348            add_selections_state: self.add_selections_state.clone(),
 5349        });
 5350    }
 5351
 5352    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5353        self.autoscroll_request = Some((autoscroll, true));
 5354        cx.notify();
 5355    }
 5356
 5357    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5358        self.autoscroll_request = Some((autoscroll, false));
 5359        cx.notify();
 5360    }
 5361
 5362    pub fn transact(
 5363        &mut self,
 5364        cx: &mut ViewContext<Self>,
 5365        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5366    ) -> Option<TransactionId> {
 5367        self.start_transaction_at(Instant::now(), cx);
 5368        update(self, cx);
 5369        self.end_transaction_at(Instant::now(), cx)
 5370    }
 5371
 5372    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5373        self.end_selection(cx);
 5374        if let Some(tx_id) = self
 5375            .buffer
 5376            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5377        {
 5378            self.selection_history
 5379                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 5380        }
 5381    }
 5382
 5383    fn end_transaction_at(
 5384        &mut self,
 5385        now: Instant,
 5386        cx: &mut ViewContext<Self>,
 5387    ) -> Option<TransactionId> {
 5388        if let Some(tx_id) = self
 5389            .buffer
 5390            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5391        {
 5392            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5393                *end_selections = Some(self.selections.disjoint_anchors());
 5394            } else {
 5395                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5396            }
 5397
 5398            cx.emit(Event::Edited);
 5399            Some(tx_id)
 5400        } else {
 5401            None
 5402        }
 5403    }
 5404
 5405    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5406        log::info!("Editor::page_up");
 5407    }
 5408
 5409    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5410        log::info!("Editor::page_down");
 5411    }
 5412
 5413    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5414        let mut fold_ranges = Vec::new();
 5415
 5416        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5417        let selections = self.selections.all::<Point>(cx);
 5418        for selection in selections {
 5419            let range = selection.display_range(&display_map).sorted();
 5420            let buffer_start_row = range.start.to_point(&display_map).row;
 5421
 5422            for row in (0..=range.end.row()).rev() {
 5423                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5424                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5425                    if fold_range.end.row >= buffer_start_row {
 5426                        fold_ranges.push(fold_range);
 5427                        if row <= range.start.row() {
 5428                            break;
 5429                        }
 5430                    }
 5431                }
 5432            }
 5433        }
 5434
 5435        self.fold_ranges(fold_ranges, cx);
 5436    }
 5437
 5438    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5439        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5440        let buffer = &display_map.buffer_snapshot;
 5441        let selections = self.selections.all::<Point>(cx);
 5442        let ranges = selections
 5443            .iter()
 5444            .map(|s| {
 5445                let range = s.display_range(&display_map).sorted();
 5446                let mut start = range.start.to_point(&display_map);
 5447                let mut end = range.end.to_point(&display_map);
 5448                start.column = 0;
 5449                end.column = buffer.line_len(end.row);
 5450                start..end
 5451            })
 5452            .collect::<Vec<_>>();
 5453        self.unfold_ranges(ranges, true, cx);
 5454    }
 5455
 5456    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5457        let max_point = display_map.max_point();
 5458        if display_row >= max_point.row() {
 5459            false
 5460        } else {
 5461            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5462            if is_blank {
 5463                false
 5464            } else {
 5465                for display_row in display_row + 1..=max_point.row() {
 5466                    let (indent, is_blank) = display_map.line_indent(display_row);
 5467                    if !is_blank {
 5468                        return indent > start_indent;
 5469                    }
 5470                }
 5471                false
 5472            }
 5473        }
 5474    }
 5475
 5476    fn foldable_range_for_line(
 5477        &self,
 5478        display_map: &DisplaySnapshot,
 5479        start_row: u32,
 5480    ) -> Range<Point> {
 5481        let max_point = display_map.max_point();
 5482
 5483        let (start_indent, _) = display_map.line_indent(start_row);
 5484        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5485        let mut end = None;
 5486        for row in start_row + 1..=max_point.row() {
 5487            let (indent, is_blank) = display_map.line_indent(row);
 5488            if !is_blank && indent <= start_indent {
 5489                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5490                break;
 5491            }
 5492        }
 5493
 5494        let end = end.unwrap_or(max_point);
 5495        start.to_point(display_map)..end.to_point(display_map)
 5496    }
 5497
 5498    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5499        let selections = self.selections.all::<Point>(cx);
 5500        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5501        self.fold_ranges(ranges, cx);
 5502    }
 5503
 5504    pub fn fold_ranges<T: ToOffset>(
 5505        &mut self,
 5506        ranges: impl IntoIterator<Item = Range<T>>,
 5507        cx: &mut ViewContext<Self>,
 5508    ) {
 5509        let mut ranges = ranges.into_iter().peekable();
 5510        if ranges.peek().is_some() {
 5511            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5512            self.request_autoscroll(Autoscroll::Fit, cx);
 5513            cx.notify();
 5514        }
 5515    }
 5516
 5517    pub fn unfold_ranges<T: ToOffset>(
 5518        &mut self,
 5519        ranges: impl IntoIterator<Item = Range<T>>,
 5520        inclusive: bool,
 5521        cx: &mut ViewContext<Self>,
 5522    ) {
 5523        let mut ranges = ranges.into_iter().peekable();
 5524        if ranges.peek().is_some() {
 5525            self.display_map
 5526                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5527            self.request_autoscroll(Autoscroll::Fit, cx);
 5528            cx.notify();
 5529        }
 5530    }
 5531
 5532    pub fn insert_blocks(
 5533        &mut self,
 5534        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5535        cx: &mut ViewContext<Self>,
 5536    ) -> Vec<BlockId> {
 5537        let blocks = self
 5538            .display_map
 5539            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5540        self.request_autoscroll(Autoscroll::Fit, cx);
 5541        blocks
 5542    }
 5543
 5544    pub fn replace_blocks(
 5545        &mut self,
 5546        blocks: HashMap<BlockId, RenderBlock>,
 5547        cx: &mut ViewContext<Self>,
 5548    ) {
 5549        self.display_map
 5550            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5551        self.request_autoscroll(Autoscroll::Fit, cx);
 5552    }
 5553
 5554    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5555        self.display_map.update(cx, |display_map, cx| {
 5556            display_map.remove_blocks(block_ids, cx)
 5557        });
 5558    }
 5559
 5560    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5561        self.display_map
 5562            .update(cx, |map, cx| map.snapshot(cx))
 5563            .longest_row()
 5564    }
 5565
 5566    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5567        self.display_map
 5568            .update(cx, |map, cx| map.snapshot(cx))
 5569            .max_point()
 5570    }
 5571
 5572    pub fn text(&self, cx: &AppContext) -> String {
 5573        self.buffer.read(cx).read(cx).text()
 5574    }
 5575
 5576    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 5577        self.transact(cx, |this, cx| {
 5578            this.buffer
 5579                .read(cx)
 5580                .as_singleton()
 5581                .expect("you can only call set_text on editors for singleton buffers")
 5582                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5583        });
 5584    }
 5585
 5586    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5587        self.display_map
 5588            .update(cx, |map, cx| map.snapshot(cx))
 5589            .text()
 5590    }
 5591
 5592    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5593        let language_name = self
 5594            .buffer
 5595            .read(cx)
 5596            .as_singleton()
 5597            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5598            .map(|l| l.name());
 5599
 5600        let settings = cx.global::<Settings>();
 5601        let mode = self
 5602            .soft_wrap_mode_override
 5603            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5604        match mode {
 5605            settings::SoftWrap::None => SoftWrap::None,
 5606            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5607            settings::SoftWrap::PreferredLineLength => {
 5608                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5609            }
 5610        }
 5611    }
 5612
 5613    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5614        self.soft_wrap_mode_override = Some(mode);
 5615        cx.notify();
 5616    }
 5617
 5618    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5619        self.display_map
 5620            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5621    }
 5622
 5623    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5624        self.highlighted_rows = rows;
 5625    }
 5626
 5627    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5628        self.highlighted_rows.clone()
 5629    }
 5630
 5631    pub fn highlight_background<T: 'static>(
 5632        &mut self,
 5633        ranges: Vec<Range<Anchor>>,
 5634        color_fetcher: fn(&Theme) -> Color,
 5635        cx: &mut ViewContext<Self>,
 5636    ) {
 5637        self.background_highlights
 5638            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5639        cx.notify();
 5640    }
 5641
 5642    #[allow(clippy::type_complexity)]
 5643    pub fn clear_background_highlights<T: 'static>(
 5644        &mut self,
 5645        cx: &mut ViewContext<Self>,
 5646    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5647        cx.notify();
 5648        self.background_highlights.remove(&TypeId::of::<T>())
 5649    }
 5650
 5651    #[cfg(feature = "test-support")]
 5652    pub fn all_background_highlights(
 5653        &mut self,
 5654        cx: &mut ViewContext<Self>,
 5655    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5656        let snapshot = self.snapshot(cx);
 5657        let buffer = &snapshot.buffer_snapshot;
 5658        let start = buffer.anchor_before(0);
 5659        let end = buffer.anchor_after(buffer.len());
 5660        let theme = cx.global::<Settings>().theme.as_ref();
 5661        self.background_highlights_in_range(start..end, &snapshot, theme)
 5662    }
 5663
 5664    fn document_highlights_for_position<'a>(
 5665        &'a self,
 5666        position: Anchor,
 5667        buffer: &'a MultiBufferSnapshot,
 5668    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5669        let read_highlights = self
 5670            .background_highlights
 5671            .get(&TypeId::of::<DocumentHighlightRead>())
 5672            .map(|h| &h.1);
 5673        let write_highlights = self
 5674            .background_highlights
 5675            .get(&TypeId::of::<DocumentHighlightWrite>())
 5676            .map(|h| &h.1);
 5677        let left_position = position.bias_left(buffer);
 5678        let right_position = position.bias_right(buffer);
 5679        read_highlights
 5680            .into_iter()
 5681            .chain(write_highlights)
 5682            .flat_map(move |ranges| {
 5683                let start_ix = match ranges.binary_search_by(|probe| {
 5684                    let cmp = probe.end.cmp(&left_position, buffer);
 5685                    if cmp.is_ge() {
 5686                        Ordering::Greater
 5687                    } else {
 5688                        Ordering::Less
 5689                    }
 5690                }) {
 5691                    Ok(i) | Err(i) => i,
 5692                };
 5693
 5694                let right_position = right_position.clone();
 5695                ranges[start_ix..]
 5696                    .iter()
 5697                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 5698            })
 5699    }
 5700
 5701    pub fn background_highlights_in_range(
 5702        &self,
 5703        search_range: Range<Anchor>,
 5704        display_snapshot: &DisplaySnapshot,
 5705        theme: &Theme,
 5706    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5707        let mut results = Vec::new();
 5708        let buffer = &display_snapshot.buffer_snapshot;
 5709        for (color_fetcher, ranges) in self.background_highlights.values() {
 5710            let color = color_fetcher(theme);
 5711            let start_ix = match ranges.binary_search_by(|probe| {
 5712                let cmp = probe.end.cmp(&search_range.start, buffer);
 5713                if cmp.is_gt() {
 5714                    Ordering::Greater
 5715                } else {
 5716                    Ordering::Less
 5717                }
 5718            }) {
 5719                Ok(i) | Err(i) => i,
 5720            };
 5721            for range in &ranges[start_ix..] {
 5722                if range.start.cmp(&search_range.end, buffer).is_ge() {
 5723                    break;
 5724                }
 5725                let start = range
 5726                    .start
 5727                    .to_point(buffer)
 5728                    .to_display_point(display_snapshot);
 5729                let end = range
 5730                    .end
 5731                    .to_point(buffer)
 5732                    .to_display_point(display_snapshot);
 5733                results.push((start..end, color))
 5734            }
 5735        }
 5736        results
 5737    }
 5738
 5739    pub fn highlight_text<T: 'static>(
 5740        &mut self,
 5741        ranges: Vec<Range<Anchor>>,
 5742        style: HighlightStyle,
 5743        cx: &mut ViewContext<Self>,
 5744    ) {
 5745        self.display_map.update(cx, |map, _| {
 5746            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5747        });
 5748        cx.notify();
 5749    }
 5750
 5751    pub fn text_highlights<'a, T: 'static>(
 5752        &'a self,
 5753        cx: &'a AppContext,
 5754    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 5755        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 5756    }
 5757
 5758    pub fn clear_text_highlights<T: 'static>(
 5759        &mut self,
 5760        cx: &mut ViewContext<Self>,
 5761    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5762        cx.notify();
 5763        self.display_map
 5764            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5765    }
 5766
 5767    fn next_blink_epoch(&mut self) -> usize {
 5768        self.blink_epoch += 1;
 5769        self.blink_epoch
 5770    }
 5771
 5772    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5773        if !self.focused {
 5774            return;
 5775        }
 5776
 5777        self.show_local_cursors = true;
 5778        cx.notify();
 5779
 5780        let epoch = self.next_blink_epoch();
 5781        cx.spawn(|this, mut cx| {
 5782            let this = this.downgrade();
 5783            async move {
 5784                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5785                if let Some(this) = this.upgrade(&cx) {
 5786                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5787                }
 5788            }
 5789        })
 5790        .detach();
 5791    }
 5792
 5793    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5794        if epoch == self.blink_epoch {
 5795            self.blinking_paused = false;
 5796            self.blink_cursors(epoch, cx);
 5797        }
 5798    }
 5799
 5800    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5801        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5802            self.show_local_cursors = !self.show_local_cursors;
 5803            cx.notify();
 5804
 5805            let epoch = self.next_blink_epoch();
 5806            cx.spawn(|this, mut cx| {
 5807                let this = this.downgrade();
 5808                async move {
 5809                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5810                    if let Some(this) = this.upgrade(&cx) {
 5811                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5812                    }
 5813                }
 5814            })
 5815            .detach();
 5816        }
 5817    }
 5818
 5819    pub fn show_local_cursors(&self) -> bool {
 5820        self.show_local_cursors && self.focused
 5821    }
 5822
 5823    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5824        cx.notify();
 5825    }
 5826
 5827    fn on_buffer_event(
 5828        &mut self,
 5829        _: ModelHandle<MultiBuffer>,
 5830        event: &language::Event,
 5831        cx: &mut ViewContext<Self>,
 5832    ) {
 5833        match event {
 5834            language::Event::Edited => {
 5835                self.refresh_active_diagnostics(cx);
 5836                self.refresh_code_actions(cx);
 5837                cx.emit(Event::BufferEdited);
 5838            }
 5839            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5840            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
 5841            language::Event::Saved => cx.emit(Event::Saved),
 5842            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5843            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5844            language::Event::Closed => cx.emit(Event::Closed),
 5845            language::Event::DiagnosticsUpdated => {
 5846                self.refresh_active_diagnostics(cx);
 5847            }
 5848            _ => {}
 5849        }
 5850    }
 5851
 5852    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5853        cx.notify();
 5854    }
 5855
 5856    pub fn set_searchable(&mut self, searchable: bool) {
 5857        self.searchable = searchable;
 5858    }
 5859
 5860    pub fn searchable(&self) -> bool {
 5861        self.searchable
 5862    }
 5863
 5864    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5865        let active_item = workspace.active_item(cx);
 5866        let editor_handle = if let Some(editor) = active_item
 5867            .as_ref()
 5868            .and_then(|item| item.act_as::<Self>(cx))
 5869        {
 5870            editor
 5871        } else {
 5872            cx.propagate_action();
 5873            return;
 5874        };
 5875
 5876        let editor = editor_handle.read(cx);
 5877        let buffer = editor.buffer.read(cx);
 5878        if buffer.is_singleton() {
 5879            cx.propagate_action();
 5880            return;
 5881        }
 5882
 5883        let mut new_selections_by_buffer = HashMap::default();
 5884        for selection in editor.selections.all::<usize>(cx) {
 5885            for (buffer, mut range) in
 5886                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5887            {
 5888                if selection.reversed {
 5889                    mem::swap(&mut range.start, &mut range.end);
 5890                }
 5891                new_selections_by_buffer
 5892                    .entry(buffer)
 5893                    .or_insert(Vec::new())
 5894                    .push(range)
 5895            }
 5896        }
 5897
 5898        editor_handle.update(cx, |editor, cx| {
 5899            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 5900        });
 5901        let pane = workspace.active_pane().clone();
 5902        pane.update(cx, |pane, _| pane.disable_history());
 5903
 5904        // We defer the pane interaction because we ourselves are a workspace item
 5905        // and activating a new item causes the pane to call a method on us reentrantly,
 5906        // which panics if we're on the stack.
 5907        cx.defer(move |workspace, cx| {
 5908            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5909                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5910                editor.update(cx, |editor, cx| {
 5911                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5912                        s.select_ranges(ranges);
 5913                    });
 5914                });
 5915            }
 5916
 5917            pane.update(cx, |pane, _| pane.enable_history());
 5918        });
 5919    }
 5920
 5921    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
 5922        let editor = workspace.open_path(action.path.clone(), true, cx);
 5923        let position = action.position;
 5924        let anchor = action.anchor;
 5925        cx.spawn_weak(|_, mut cx| async move {
 5926            let editor = editor.await.log_err()?.downcast::<Editor>()?;
 5927            editor.update(&mut cx, |editor, cx| {
 5928                let buffer = editor.buffer().read(cx).as_singleton()?;
 5929                let buffer = buffer.read(cx);
 5930                let cursor = if buffer.can_resolve(&anchor) {
 5931                    language::ToPoint::to_point(&anchor, buffer)
 5932                } else {
 5933                    buffer.clip_point(position, Bias::Left)
 5934                };
 5935
 5936                let nav_history = editor.nav_history.take();
 5937                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5938                    s.select_ranges([cursor..cursor]);
 5939                });
 5940                editor.nav_history = nav_history;
 5941
 5942                Some(())
 5943            })?;
 5944            Some(())
 5945        })
 5946        .detach()
 5947    }
 5948
 5949    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 5950        let snapshot = self.buffer.read(cx).read(cx);
 5951        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 5952        Some(
 5953            ranges
 5954                .iter()
 5955                .map(move |range| {
 5956                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 5957                })
 5958                .collect(),
 5959        )
 5960    }
 5961
 5962    fn selection_replacement_ranges(
 5963        &self,
 5964        range: Range<OffsetUtf16>,
 5965        cx: &AppContext,
 5966    ) -> Vec<Range<OffsetUtf16>> {
 5967        let selections = self.selections.all::<OffsetUtf16>(cx);
 5968        let newest_selection = selections
 5969            .iter()
 5970            .max_by_key(|selection| selection.id)
 5971            .unwrap();
 5972        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 5973        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 5974        let snapshot = self.buffer.read(cx).read(cx);
 5975        selections
 5976            .into_iter()
 5977            .map(|mut selection| {
 5978                selection.start.0 =
 5979                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 5980                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 5981                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 5982                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 5983            })
 5984            .collect()
 5985    }
 5986}
 5987
 5988impl EditorSnapshot {
 5989    pub fn is_focused(&self) -> bool {
 5990        self.is_focused
 5991    }
 5992
 5993    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5994        self.placeholder_text.as_ref()
 5995    }
 5996
 5997    pub fn scroll_position(&self) -> Vector2F {
 5998        compute_scroll_position(
 5999            &self.display_snapshot,
 6000            self.scroll_position,
 6001            &self.scroll_top_anchor,
 6002        )
 6003    }
 6004}
 6005
 6006impl Deref for EditorSnapshot {
 6007    type Target = DisplaySnapshot;
 6008
 6009    fn deref(&self) -> &Self::Target {
 6010        &self.display_snapshot
 6011    }
 6012}
 6013
 6014fn compute_scroll_position(
 6015    snapshot: &DisplaySnapshot,
 6016    mut scroll_position: Vector2F,
 6017    scroll_top_anchor: &Anchor,
 6018) -> Vector2F {
 6019    if *scroll_top_anchor != Anchor::min() {
 6020        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 6021        scroll_position.set_y(scroll_top + scroll_position.y());
 6022    } else {
 6023        scroll_position.set_y(0.);
 6024    }
 6025    scroll_position
 6026}
 6027
 6028#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 6029pub enum Event {
 6030    BufferEdited,
 6031    Edited,
 6032    Reparsed,
 6033    Blurred,
 6034    DirtyChanged,
 6035    Saved,
 6036    TitleChanged,
 6037    SelectionsChanged { local: bool },
 6038    ScrollPositionChanged { local: bool },
 6039    Closed,
 6040    IgnoredInput,
 6041}
 6042
 6043pub struct EditorFocused(pub ViewHandle<Editor>);
 6044pub struct EditorBlurred(pub ViewHandle<Editor>);
 6045pub struct EditorReleased(pub WeakViewHandle<Editor>);
 6046
 6047impl Entity for Editor {
 6048    type Event = Event;
 6049
 6050    fn release(&mut self, cx: &mut MutableAppContext) {
 6051        cx.emit_global(EditorReleased(self.handle.clone()));
 6052    }
 6053}
 6054
 6055impl View for Editor {
 6056    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 6057        let style = self.style(cx);
 6058        let font_changed = self.display_map.update(cx, |map, cx| {
 6059            map.set_font(style.text.font_id, style.text.font_size, cx)
 6060        });
 6061
 6062        if font_changed {
 6063            let handle = self.handle.clone();
 6064            cx.defer(move |cx| {
 6065                if let Some(editor) = handle.upgrade(cx) {
 6066                    editor.update(cx, |editor, cx| {
 6067                        hide_hover(editor, cx);
 6068                        hide_link_definition(editor, cx);
 6069                    })
 6070                }
 6071            });
 6072        }
 6073
 6074        Stack::new()
 6075            .with_child(
 6076                EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed(),
 6077            )
 6078            .with_child(ChildView::new(&self.mouse_context_menu).boxed())
 6079            .boxed()
 6080    }
 6081
 6082    fn ui_name() -> &'static str {
 6083        "Editor"
 6084    }
 6085
 6086    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
 6087        let focused_event = EditorFocused(cx.handle());
 6088        cx.emit_global(focused_event);
 6089        if let Some(rename) = self.pending_rename.as_ref() {
 6090            cx.focus(&rename.editor);
 6091        } else {
 6092            self.focused = true;
 6093            self.blink_cursors(self.blink_epoch, cx);
 6094            self.buffer.update(cx, |buffer, cx| {
 6095                buffer.finalize_last_transaction(cx);
 6096                if self.leader_replica_id.is_none() {
 6097                    buffer.set_active_selections(
 6098                        &self.selections.disjoint_anchors(),
 6099                        self.selections.line_mode,
 6100                        cx,
 6101                    );
 6102                }
 6103            });
 6104        }
 6105    }
 6106
 6107    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
 6108        let blurred_event = EditorBlurred(cx.handle());
 6109        cx.emit_global(blurred_event);
 6110        self.focused = false;
 6111        self.buffer
 6112            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6113        self.hide_context_menu(cx);
 6114        hide_hover(self, cx);
 6115        cx.emit(Event::Blurred);
 6116        cx.notify();
 6117    }
 6118
 6119    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6120        let mut context = Self::default_keymap_context();
 6121        let mode = match self.mode {
 6122            EditorMode::SingleLine => "single_line",
 6123            EditorMode::AutoHeight { .. } => "auto_height",
 6124            EditorMode::Full => "full",
 6125        };
 6126        context.map.insert("mode".into(), mode.into());
 6127        if self.pending_rename.is_some() {
 6128            context.set.insert("renaming".into());
 6129        }
 6130        match self.context_menu.as_ref() {
 6131            Some(ContextMenu::Completions(_)) => {
 6132                context.set.insert("showing_completions".into());
 6133            }
 6134            Some(ContextMenu::CodeActions(_)) => {
 6135                context.set.insert("showing_code_actions".into());
 6136            }
 6137            None => {}
 6138        }
 6139
 6140        for layer in self.keymap_context_layers.values() {
 6141            context.extend(layer);
 6142        }
 6143
 6144        context
 6145    }
 6146
 6147    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
 6148        Some(
 6149            self.buffer
 6150                .read(cx)
 6151                .read(cx)
 6152                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 6153                .collect(),
 6154        )
 6155    }
 6156
 6157    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6158        // Prevent the IME menu from appearing when holding down an alphabetic key
 6159        // while input is disabled.
 6160        if !self.input_enabled {
 6161            return None;
 6162        }
 6163
 6164        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 6165        Some(range.start.0..range.end.0)
 6166    }
 6167
 6168    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6169        let snapshot = self.buffer.read(cx).read(cx);
 6170        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 6171        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 6172    }
 6173
 6174    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 6175        self.clear_text_highlights::<InputComposition>(cx);
 6176        self.ime_transaction.take();
 6177    }
 6178
 6179    fn replace_text_in_range(
 6180        &mut self,
 6181        range_utf16: Option<Range<usize>>,
 6182        text: &str,
 6183        cx: &mut ViewContext<Self>,
 6184    ) {
 6185        if !self.input_enabled {
 6186            cx.emit(Event::IgnoredInput);
 6187            return;
 6188        }
 6189
 6190        self.transact(cx, |this, cx| {
 6191            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 6192                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6193                Some(this.selection_replacement_ranges(range_utf16, cx))
 6194            } else {
 6195                this.marked_text_ranges(cx)
 6196            };
 6197
 6198            if let Some(new_selected_ranges) = new_selected_ranges {
 6199                this.change_selections(None, cx, |selections| {
 6200                    selections.select_ranges(new_selected_ranges)
 6201                });
 6202            }
 6203            this.handle_input(text, cx);
 6204        });
 6205
 6206        if let Some(transaction) = self.ime_transaction {
 6207            self.buffer.update(cx, |buffer, cx| {
 6208                buffer.group_until_transaction(transaction, cx);
 6209            });
 6210        }
 6211
 6212        self.unmark_text(cx);
 6213    }
 6214
 6215    fn replace_and_mark_text_in_range(
 6216        &mut self,
 6217        range_utf16: Option<Range<usize>>,
 6218        text: &str,
 6219        new_selected_range_utf16: Option<Range<usize>>,
 6220        cx: &mut ViewContext<Self>,
 6221    ) {
 6222        if !self.input_enabled {
 6223            cx.emit(Event::IgnoredInput);
 6224            return;
 6225        }
 6226
 6227        let transaction = self.transact(cx, |this, cx| {
 6228            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 6229                let snapshot = this.buffer.read(cx).read(cx);
 6230                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 6231                    for marked_range in &mut marked_ranges {
 6232                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 6233                        marked_range.start.0 += relative_range_utf16.start;
 6234                        marked_range.start =
 6235                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 6236                        marked_range.end =
 6237                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 6238                    }
 6239                }
 6240                Some(marked_ranges)
 6241            } else if let Some(range_utf16) = range_utf16 {
 6242                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6243                Some(this.selection_replacement_ranges(range_utf16, cx))
 6244            } else {
 6245                None
 6246            };
 6247
 6248            if let Some(ranges) = ranges_to_replace {
 6249                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 6250            }
 6251
 6252            let marked_ranges = {
 6253                let snapshot = this.buffer.read(cx).read(cx);
 6254                this.selections
 6255                    .disjoint_anchors()
 6256                    .iter()
 6257                    .map(|selection| {
 6258                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 6259                    })
 6260                    .collect::<Vec<_>>()
 6261            };
 6262
 6263            if text.is_empty() {
 6264                this.unmark_text(cx);
 6265            } else {
 6266                this.highlight_text::<InputComposition>(
 6267                    marked_ranges.clone(),
 6268                    this.style(cx).composition_mark,
 6269                    cx,
 6270                );
 6271            }
 6272
 6273            this.handle_input(text, cx);
 6274
 6275            if let Some(new_selected_range) = new_selected_range_utf16 {
 6276                let snapshot = this.buffer.read(cx).read(cx);
 6277                let new_selected_ranges = marked_ranges
 6278                    .into_iter()
 6279                    .map(|marked_range| {
 6280                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 6281                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 6282                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 6283                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 6284                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 6285                    })
 6286                    .collect::<Vec<_>>();
 6287
 6288                drop(snapshot);
 6289                this.change_selections(None, cx, |selections| {
 6290                    selections.select_ranges(new_selected_ranges)
 6291                });
 6292            }
 6293        });
 6294
 6295        self.ime_transaction = self.ime_transaction.or(transaction);
 6296        if let Some(transaction) = self.ime_transaction {
 6297            self.buffer.update(cx, |buffer, cx| {
 6298                buffer.group_until_transaction(transaction, cx);
 6299            });
 6300        }
 6301
 6302        if self.text_highlights::<InputComposition>(cx).is_none() {
 6303            self.ime_transaction.take();
 6304        }
 6305    }
 6306}
 6307
 6308fn build_style(
 6309    settings: &Settings,
 6310    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6311    override_text_style: Option<&OverrideTextStyle>,
 6312    cx: &AppContext,
 6313) -> EditorStyle {
 6314    let font_cache = cx.font_cache();
 6315
 6316    let mut theme = settings.theme.editor.clone();
 6317    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6318        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6319        theme.text_color = field_editor_theme.text.color;
 6320        theme.selection = field_editor_theme.selection;
 6321        theme.background = field_editor_theme
 6322            .container
 6323            .background_color
 6324            .unwrap_or_default();
 6325        EditorStyle {
 6326            text: field_editor_theme.text,
 6327            placeholder_text: field_editor_theme.placeholder_text,
 6328            theme,
 6329        }
 6330    } else {
 6331        let font_family_id = settings.buffer_font_family;
 6332        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6333        let font_properties = Default::default();
 6334        let font_id = font_cache
 6335            .select_font(font_family_id, &font_properties)
 6336            .unwrap();
 6337        let font_size = settings.buffer_font_size;
 6338        EditorStyle {
 6339            text: TextStyle {
 6340                color: settings.theme.editor.text_color,
 6341                font_family_name,
 6342                font_family_id,
 6343                font_id,
 6344                font_size,
 6345                font_properties,
 6346                underline: Default::default(),
 6347            },
 6348            placeholder_text: None,
 6349            theme,
 6350        }
 6351    };
 6352
 6353    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6354        if let Some(highlighted) = style
 6355            .text
 6356            .clone()
 6357            .highlight(highlight_style, font_cache)
 6358            .log_err()
 6359        {
 6360            style.text = highlighted;
 6361        }
 6362    }
 6363
 6364    style
 6365}
 6366
 6367trait SelectionExt {
 6368    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6369    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6370    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6371    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6372        -> Range<u32>;
 6373}
 6374
 6375impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6376    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6377        let start = self.start.to_point(buffer);
 6378        let end = self.end.to_point(buffer);
 6379        if self.reversed {
 6380            end..start
 6381        } else {
 6382            start..end
 6383        }
 6384    }
 6385
 6386    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6387        let start = self.start.to_offset(buffer);
 6388        let end = self.end.to_offset(buffer);
 6389        if self.reversed {
 6390            end..start
 6391        } else {
 6392            start..end
 6393        }
 6394    }
 6395
 6396    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6397        let start = self
 6398            .start
 6399            .to_point(&map.buffer_snapshot)
 6400            .to_display_point(map);
 6401        let end = self
 6402            .end
 6403            .to_point(&map.buffer_snapshot)
 6404            .to_display_point(map);
 6405        if self.reversed {
 6406            end..start
 6407        } else {
 6408            start..end
 6409        }
 6410    }
 6411
 6412    fn spanned_rows(
 6413        &self,
 6414        include_end_if_at_line_start: bool,
 6415        map: &DisplaySnapshot,
 6416    ) -> Range<u32> {
 6417        let start = self.start.to_point(&map.buffer_snapshot);
 6418        let mut end = self.end.to_point(&map.buffer_snapshot);
 6419        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6420            end.row -= 1;
 6421        }
 6422
 6423        let buffer_start = map.prev_line_boundary(start).0;
 6424        let buffer_end = map.next_line_boundary(end).0;
 6425        buffer_start.row..buffer_end.row + 1
 6426    }
 6427}
 6428
 6429impl<T: InvalidationRegion> InvalidationStack<T> {
 6430    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6431    where
 6432        S: Clone + ToOffset,
 6433    {
 6434        while let Some(region) = self.last() {
 6435            let all_selections_inside_invalidation_ranges =
 6436                if selections.len() == region.ranges().len() {
 6437                    selections
 6438                        .iter()
 6439                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 6440                        .all(|(selection, invalidation_range)| {
 6441                            let head = selection.head().to_offset(buffer);
 6442                            invalidation_range.start <= head && invalidation_range.end >= head
 6443                        })
 6444                } else {
 6445                    false
 6446                };
 6447
 6448            if all_selections_inside_invalidation_ranges {
 6449                break;
 6450            } else {
 6451                self.pop();
 6452            }
 6453        }
 6454    }
 6455}
 6456
 6457impl<T> Default for InvalidationStack<T> {
 6458    fn default() -> Self {
 6459        Self(Default::default())
 6460    }
 6461}
 6462
 6463impl<T> Deref for InvalidationStack<T> {
 6464    type Target = Vec<T>;
 6465
 6466    fn deref(&self) -> &Self::Target {
 6467        &self.0
 6468    }
 6469}
 6470
 6471impl<T> DerefMut for InvalidationStack<T> {
 6472    fn deref_mut(&mut self) -> &mut Self::Target {
 6473        &mut self.0
 6474    }
 6475}
 6476
 6477impl InvalidationRegion for BracketPairState {
 6478    fn ranges(&self) -> &[Range<Anchor>] {
 6479        &self.ranges
 6480    }
 6481}
 6482
 6483impl InvalidationRegion for SnippetState {
 6484    fn ranges(&self) -> &[Range<Anchor>] {
 6485        &self.ranges[self.active_index]
 6486    }
 6487}
 6488
 6489impl Deref for EditorStyle {
 6490    type Target = theme::Editor;
 6491
 6492    fn deref(&self) -> &Self::Target {
 6493        &self.theme
 6494    }
 6495}
 6496
 6497pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6498    let mut highlighted_lines = Vec::new();
 6499    for line in diagnostic.message.lines() {
 6500        highlighted_lines.push(highlight_diagnostic_message(line));
 6501    }
 6502
 6503    Arc::new(move |cx: &mut BlockContext| {
 6504        let settings = cx.global::<Settings>();
 6505        let theme = &settings.theme.editor;
 6506        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6507        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6508        Flex::column()
 6509            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6510                Label::new(
 6511                    line.clone(),
 6512                    style.message.clone().with_font_size(font_size),
 6513                )
 6514                .with_highlights(highlights.clone())
 6515                .contained()
 6516                .with_margin_left(cx.anchor_x)
 6517                .boxed()
 6518            }))
 6519            .aligned()
 6520            .left()
 6521            .boxed()
 6522    })
 6523}
 6524
 6525pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6526    let mut message_without_backticks = String::new();
 6527    let mut prev_offset = 0;
 6528    let mut inside_block = false;
 6529    let mut highlights = Vec::new();
 6530    for (match_ix, (offset, _)) in message
 6531        .match_indices('`')
 6532        .chain([(message.len(), "")])
 6533        .enumerate()
 6534    {
 6535        message_without_backticks.push_str(&message[prev_offset..offset]);
 6536        if inside_block {
 6537            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6538        }
 6539
 6540        inside_block = !inside_block;
 6541        prev_offset = offset + 1;
 6542    }
 6543
 6544    (message_without_backticks, highlights)
 6545}
 6546
 6547pub fn diagnostic_style(
 6548    severity: DiagnosticSeverity,
 6549    valid: bool,
 6550    theme: &theme::Editor,
 6551) -> DiagnosticStyle {
 6552    match (severity, valid) {
 6553        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6554        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6555        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6556        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6557        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6558        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6559        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6560        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6561        _ => theme.invalid_hint_diagnostic.clone(),
 6562    }
 6563}
 6564
 6565pub fn combine_syntax_and_fuzzy_match_highlights(
 6566    text: &str,
 6567    default_style: HighlightStyle,
 6568    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6569    match_indices: &[usize],
 6570) -> Vec<(Range<usize>, HighlightStyle)> {
 6571    let mut result = Vec::new();
 6572    let mut match_indices = match_indices.iter().copied().peekable();
 6573
 6574    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6575    {
 6576        syntax_highlight.weight = None;
 6577
 6578        // Add highlights for any fuzzy match characters before the next
 6579        // syntax highlight range.
 6580        while let Some(&match_index) = match_indices.peek() {
 6581            if match_index >= range.start {
 6582                break;
 6583            }
 6584            match_indices.next();
 6585            let end_index = char_ix_after(match_index, text);
 6586            let mut match_style = default_style;
 6587            match_style.weight = Some(fonts::Weight::BOLD);
 6588            result.push((match_index..end_index, match_style));
 6589        }
 6590
 6591        if range.start == usize::MAX {
 6592            break;
 6593        }
 6594
 6595        // Add highlights for any fuzzy match characters within the
 6596        // syntax highlight range.
 6597        let mut offset = range.start;
 6598        while let Some(&match_index) = match_indices.peek() {
 6599            if match_index >= range.end {
 6600                break;
 6601            }
 6602
 6603            match_indices.next();
 6604            if match_index > offset {
 6605                result.push((offset..match_index, syntax_highlight));
 6606            }
 6607
 6608            let mut end_index = char_ix_after(match_index, text);
 6609            while let Some(&next_match_index) = match_indices.peek() {
 6610                if next_match_index == end_index && next_match_index < range.end {
 6611                    end_index = char_ix_after(next_match_index, text);
 6612                    match_indices.next();
 6613                } else {
 6614                    break;
 6615                }
 6616            }
 6617
 6618            let mut match_style = syntax_highlight;
 6619            match_style.weight = Some(fonts::Weight::BOLD);
 6620            result.push((match_index..end_index, match_style));
 6621            offset = end_index;
 6622        }
 6623
 6624        if offset < range.end {
 6625            result.push((offset..range.end, syntax_highlight));
 6626        }
 6627    }
 6628
 6629    fn char_ix_after(ix: usize, text: &str) -> usize {
 6630        ix + text[ix..].chars().next().unwrap().len_utf8()
 6631    }
 6632
 6633    result
 6634}
 6635
 6636pub fn styled_runs_for_code_label<'a>(
 6637    label: &'a CodeLabel,
 6638    syntax_theme: &'a theme::SyntaxTheme,
 6639) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6640    let fade_out = HighlightStyle {
 6641        fade_out: Some(0.35),
 6642        ..Default::default()
 6643    };
 6644
 6645    let mut prev_end = label.filter_range.end;
 6646    label
 6647        .runs
 6648        .iter()
 6649        .enumerate()
 6650        .flat_map(move |(ix, (range, highlight_id))| {
 6651            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6652                style
 6653            } else {
 6654                return Default::default();
 6655            };
 6656            let mut muted_style = style;
 6657            muted_style.highlight(fade_out);
 6658
 6659            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6660            if range.start >= label.filter_range.end {
 6661                if range.start > prev_end {
 6662                    runs.push((prev_end..range.start, fade_out));
 6663                }
 6664                runs.push((range.clone(), muted_style));
 6665            } else if range.end <= label.filter_range.end {
 6666                runs.push((range.clone(), style));
 6667            } else {
 6668                runs.push((range.start..label.filter_range.end, style));
 6669                runs.push((label.filter_range.end..range.end, muted_style));
 6670            }
 6671            prev_end = cmp::max(prev_end, range.end);
 6672
 6673            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6674                runs.push((prev_end..label.text.len(), fade_out));
 6675            }
 6676
 6677            runs
 6678        })
 6679}
 6680
 6681#[cfg(test)]
 6682mod tests {
 6683    use crate::test::{
 6684        assert_text_with_selections, build_editor, select_ranges, EditorLspTestContext,
 6685        EditorTestContext,
 6686    };
 6687
 6688    use super::*;
 6689    use futures::StreamExt;
 6690    use gpui::{
 6691        geometry::rect::RectF,
 6692        platform::{WindowBounds, WindowOptions},
 6693    };
 6694    use indoc::indoc;
 6695    use language::{FakeLspAdapter, LanguageConfig};
 6696    use project::FakeFs;
 6697    use settings::EditorSettings;
 6698    use std::{cell::RefCell, rc::Rc, time::Instant};
 6699    use text::Point;
 6700    use unindent::Unindent;
 6701    use util::{
 6702        assert_set_eq,
 6703        test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
 6704    };
 6705    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6706
 6707    #[gpui::test]
 6708    fn test_edit_events(cx: &mut MutableAppContext) {
 6709        cx.set_global(Settings::test(cx));
 6710        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6711
 6712        let events = Rc::new(RefCell::new(Vec::new()));
 6713        let (_, editor1) = cx.add_window(Default::default(), {
 6714            let events = events.clone();
 6715            |cx| {
 6716                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6717                    if matches!(
 6718                        event,
 6719                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6720                    ) {
 6721                        events.borrow_mut().push(("editor1", *event));
 6722                    }
 6723                })
 6724                .detach();
 6725                Editor::for_buffer(buffer.clone(), None, cx)
 6726            }
 6727        });
 6728        let (_, editor2) = cx.add_window(Default::default(), {
 6729            let events = events.clone();
 6730            |cx| {
 6731                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6732                    if matches!(
 6733                        event,
 6734                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6735                    ) {
 6736                        events.borrow_mut().push(("editor2", *event));
 6737                    }
 6738                })
 6739                .detach();
 6740                Editor::for_buffer(buffer.clone(), None, cx)
 6741            }
 6742        });
 6743        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6744
 6745        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6746        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6747        assert_eq!(
 6748            mem::take(&mut *events.borrow_mut()),
 6749            [
 6750                ("editor1", Event::Edited),
 6751                ("editor1", Event::BufferEdited),
 6752                ("editor2", Event::BufferEdited),
 6753                ("editor1", Event::DirtyChanged),
 6754                ("editor2", Event::DirtyChanged)
 6755            ]
 6756        );
 6757
 6758        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6759        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6760        assert_eq!(
 6761            mem::take(&mut *events.borrow_mut()),
 6762            [
 6763                ("editor2", Event::Edited),
 6764                ("editor1", Event::BufferEdited),
 6765                ("editor2", Event::BufferEdited),
 6766            ]
 6767        );
 6768
 6769        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6770        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6771        assert_eq!(
 6772            mem::take(&mut *events.borrow_mut()),
 6773            [
 6774                ("editor1", Event::Edited),
 6775                ("editor1", Event::BufferEdited),
 6776                ("editor2", Event::BufferEdited),
 6777                ("editor1", Event::DirtyChanged),
 6778                ("editor2", Event::DirtyChanged),
 6779            ]
 6780        );
 6781
 6782        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6783        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6784        assert_eq!(
 6785            mem::take(&mut *events.borrow_mut()),
 6786            [
 6787                ("editor1", Event::Edited),
 6788                ("editor1", Event::BufferEdited),
 6789                ("editor2", Event::BufferEdited),
 6790                ("editor1", Event::DirtyChanged),
 6791                ("editor2", Event::DirtyChanged),
 6792            ]
 6793        );
 6794
 6795        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6796        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6797        assert_eq!(
 6798            mem::take(&mut *events.borrow_mut()),
 6799            [
 6800                ("editor2", Event::Edited),
 6801                ("editor1", Event::BufferEdited),
 6802                ("editor2", Event::BufferEdited),
 6803                ("editor1", Event::DirtyChanged),
 6804                ("editor2", Event::DirtyChanged),
 6805            ]
 6806        );
 6807
 6808        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6809        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6810        assert_eq!(
 6811            mem::take(&mut *events.borrow_mut()),
 6812            [
 6813                ("editor2", Event::Edited),
 6814                ("editor1", Event::BufferEdited),
 6815                ("editor2", Event::BufferEdited),
 6816                ("editor1", Event::DirtyChanged),
 6817                ("editor2", Event::DirtyChanged),
 6818            ]
 6819        );
 6820
 6821        // No event is emitted when the mutation is a no-op.
 6822        editor2.update(cx, |editor, cx| {
 6823            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6824
 6825            editor.backspace(&Backspace, cx);
 6826        });
 6827        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6828    }
 6829
 6830    #[gpui::test]
 6831    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6832        cx.set_global(Settings::test(cx));
 6833        let mut now = Instant::now();
 6834        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6835        let group_interval = buffer.read(cx).transaction_group_interval();
 6836        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6837        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6838
 6839        editor.update(cx, |editor, cx| {
 6840            editor.start_transaction_at(now, cx);
 6841            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6842
 6843            editor.insert("cd", cx);
 6844            editor.end_transaction_at(now, cx);
 6845            assert_eq!(editor.text(cx), "12cd56");
 6846            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6847
 6848            editor.start_transaction_at(now, cx);
 6849            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6850            editor.insert("e", cx);
 6851            editor.end_transaction_at(now, cx);
 6852            assert_eq!(editor.text(cx), "12cde6");
 6853            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6854
 6855            now += group_interval + Duration::from_millis(1);
 6856            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6857
 6858            // Simulate an edit in another editor
 6859            buffer.update(cx, |buffer, cx| {
 6860                buffer.start_transaction_at(now, cx);
 6861                buffer.edit([(0..1, "a")], None, cx);
 6862                buffer.edit([(1..1, "b")], None, cx);
 6863                buffer.end_transaction_at(now, cx);
 6864            });
 6865
 6866            assert_eq!(editor.text(cx), "ab2cde6");
 6867            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6868
 6869            // Last transaction happened past the group interval in a different editor.
 6870            // Undo it individually and don't restore selections.
 6871            editor.undo(&Undo, cx);
 6872            assert_eq!(editor.text(cx), "12cde6");
 6873            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6874
 6875            // First two transactions happened within the group interval in this editor.
 6876            // Undo them together and restore selections.
 6877            editor.undo(&Undo, cx);
 6878            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6879            assert_eq!(editor.text(cx), "123456");
 6880            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6881
 6882            // Redo the first two transactions together.
 6883            editor.redo(&Redo, cx);
 6884            assert_eq!(editor.text(cx), "12cde6");
 6885            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6886
 6887            // Redo the last transaction on its own.
 6888            editor.redo(&Redo, cx);
 6889            assert_eq!(editor.text(cx), "ab2cde6");
 6890            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6891
 6892            // Test empty transactions.
 6893            editor.start_transaction_at(now, cx);
 6894            editor.end_transaction_at(now, cx);
 6895            editor.undo(&Undo, cx);
 6896            assert_eq!(editor.text(cx), "12cde6");
 6897        });
 6898    }
 6899
 6900    #[gpui::test]
 6901    fn test_ime_composition(cx: &mut MutableAppContext) {
 6902        cx.set_global(Settings::test(cx));
 6903        let buffer = cx.add_model(|cx| {
 6904            let mut buffer = language::Buffer::new(0, "abcde", cx);
 6905            // Ensure automatic grouping doesn't occur.
 6906            buffer.set_group_interval(Duration::ZERO);
 6907            buffer
 6908        });
 6909
 6910        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6911        cx.add_window(Default::default(), |cx| {
 6912            let mut editor = build_editor(buffer.clone(), cx);
 6913
 6914            // Start a new IME composition.
 6915            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6916            editor.replace_and_mark_text_in_range(Some(0..1), "á", None, cx);
 6917            editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
 6918            assert_eq!(editor.text(cx), "äbcde");
 6919            assert_eq!(
 6920                editor.marked_text_ranges(cx),
 6921                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6922            );
 6923
 6924            // Finalize IME composition.
 6925            editor.replace_text_in_range(None, "ā", cx);
 6926            assert_eq!(editor.text(cx), "ābcde");
 6927            assert_eq!(editor.marked_text_ranges(cx), None);
 6928
 6929            // IME composition edits are grouped and are undone/redone at once.
 6930            editor.undo(&Default::default(), cx);
 6931            assert_eq!(editor.text(cx), "abcde");
 6932            assert_eq!(editor.marked_text_ranges(cx), None);
 6933            editor.redo(&Default::default(), cx);
 6934            assert_eq!(editor.text(cx), "ābcde");
 6935            assert_eq!(editor.marked_text_ranges(cx), None);
 6936
 6937            // Start a new IME composition.
 6938            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 6939            assert_eq!(
 6940                editor.marked_text_ranges(cx),
 6941                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 6942            );
 6943
 6944            // Undoing during an IME composition cancels it.
 6945            editor.undo(&Default::default(), cx);
 6946            assert_eq!(editor.text(cx), "ābcde");
 6947            assert_eq!(editor.marked_text_ranges(cx), None);
 6948
 6949            // Start a new IME composition with an invalid marked range, ensuring it gets clipped.
 6950            editor.replace_and_mark_text_in_range(Some(4..999), "è", None, cx);
 6951            assert_eq!(editor.text(cx), "ābcdè");
 6952            assert_eq!(
 6953                editor.marked_text_ranges(cx),
 6954                Some(vec![OffsetUtf16(4)..OffsetUtf16(5)])
 6955            );
 6956
 6957            // Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
 6958            editor.replace_text_in_range(Some(4..999), "ę", cx);
 6959            assert_eq!(editor.text(cx), "ābcdę");
 6960            assert_eq!(editor.marked_text_ranges(cx), None);
 6961
 6962            // Start a new IME composition with multiple cursors.
 6963            editor.change_selections(None, cx, |s| {
 6964                s.select_ranges([
 6965                    OffsetUtf16(1)..OffsetUtf16(1),
 6966                    OffsetUtf16(3)..OffsetUtf16(3),
 6967                    OffsetUtf16(5)..OffsetUtf16(5),
 6968                ])
 6969            });
 6970            editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, cx);
 6971            assert_eq!(editor.text(cx), "XYZbXYZdXYZ");
 6972            assert_eq!(
 6973                editor.marked_text_ranges(cx),
 6974                Some(vec![
 6975                    OffsetUtf16(0)..OffsetUtf16(3),
 6976                    OffsetUtf16(4)..OffsetUtf16(7),
 6977                    OffsetUtf16(8)..OffsetUtf16(11)
 6978                ])
 6979            );
 6980
 6981            // Ensure the newly-marked range gets treated as relative to the previously-marked ranges.
 6982            editor.replace_and_mark_text_in_range(Some(1..2), "1", None, cx);
 6983            assert_eq!(editor.text(cx), "X1ZbX1ZdX1Z");
 6984            assert_eq!(
 6985                editor.marked_text_ranges(cx),
 6986                Some(vec![
 6987                    OffsetUtf16(1)..OffsetUtf16(2),
 6988                    OffsetUtf16(5)..OffsetUtf16(6),
 6989                    OffsetUtf16(9)..OffsetUtf16(10)
 6990                ])
 6991            );
 6992
 6993            // Finalize IME composition with multiple cursors.
 6994            editor.replace_text_in_range(Some(9..10), "2", cx);
 6995            assert_eq!(editor.text(cx), "X2ZbX2ZdX2Z");
 6996            assert_eq!(editor.marked_text_ranges(cx), None);
 6997
 6998            editor
 6999        });
 7000    }
 7001
 7002    #[gpui::test]
 7003    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 7004        cx.set_global(Settings::test(cx));
 7005
 7006        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 7007        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7008        editor.update(cx, |view, cx| {
 7009            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 7010        });
 7011        assert_eq!(
 7012            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7013            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 7014        );
 7015
 7016        editor.update(cx, |view, cx| {
 7017            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7018        });
 7019
 7020        assert_eq!(
 7021            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7022            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7023        );
 7024
 7025        editor.update(cx, |view, cx| {
 7026            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7027        });
 7028
 7029        assert_eq!(
 7030            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7031            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 7032        );
 7033
 7034        editor.update(cx, |view, cx| {
 7035            view.end_selection(cx);
 7036            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7037        });
 7038
 7039        assert_eq!(
 7040            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7041            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 7042        );
 7043
 7044        editor.update(cx, |view, cx| {
 7045            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 7046            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 7047        });
 7048
 7049        assert_eq!(
 7050            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7051            [
 7052                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 7053                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 7054            ]
 7055        );
 7056
 7057        editor.update(cx, |view, cx| {
 7058            view.end_selection(cx);
 7059        });
 7060
 7061        assert_eq!(
 7062            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7063            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 7064        );
 7065    }
 7066
 7067    #[gpui::test]
 7068    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 7069        cx.set_global(Settings::test(cx));
 7070        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7071        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7072
 7073        view.update(cx, |view, cx| {
 7074            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 7075            assert_eq!(
 7076                view.selections.display_ranges(cx),
 7077                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 7078            );
 7079        });
 7080
 7081        view.update(cx, |view, cx| {
 7082            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7083            assert_eq!(
 7084                view.selections.display_ranges(cx),
 7085                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7086            );
 7087        });
 7088
 7089        view.update(cx, |view, cx| {
 7090            view.cancel(&Cancel, cx);
 7091            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7092            assert_eq!(
 7093                view.selections.display_ranges(cx),
 7094                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7095            );
 7096        });
 7097    }
 7098
 7099    #[gpui::test]
 7100    fn test_clone(cx: &mut gpui::MutableAppContext) {
 7101        let (text, selection_ranges) = marked_text_ranges(
 7102            indoc! {"
 7103                one
 7104                two
 7105                threeˇ
 7106                four
 7107                fiveˇ
 7108            "},
 7109            true,
 7110        );
 7111        cx.set_global(Settings::test(cx));
 7112        let buffer = MultiBuffer::build_simple(&text, cx);
 7113
 7114        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7115
 7116        editor.update(cx, |editor, cx| {
 7117            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 7118            editor.fold_ranges(
 7119                [
 7120                    Point::new(1, 0)..Point::new(2, 0),
 7121                    Point::new(3, 0)..Point::new(4, 0),
 7122                ],
 7123                cx,
 7124            );
 7125        });
 7126
 7127        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 7128            cx.add_window(Default::default(), |cx| editor.clone(cx))
 7129        });
 7130
 7131        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 7132        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 7133
 7134        assert_eq!(
 7135            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 7136            editor.update(cx, |e, cx| e.display_text(cx))
 7137        );
 7138        assert_eq!(
 7139            cloned_snapshot
 7140                .folds_in_range(0..text.len())
 7141                .collect::<Vec<_>>(),
 7142            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 7143        );
 7144        assert_set_eq!(
 7145            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 7146            editor.read(cx).selections.ranges(cx)
 7147        );
 7148        assert_set_eq!(
 7149            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 7150            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 7151        );
 7152    }
 7153
 7154    #[gpui::test]
 7155    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 7156        cx.set_global(Settings::test(cx));
 7157        use workspace::Item;
 7158        let (_, pane) = cx.add_window(Default::default(), |cx| Pane::new(None, cx));
 7159        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 7160
 7161        cx.add_view(&pane, |cx| {
 7162            let mut editor = build_editor(buffer.clone(), cx);
 7163            let handle = cx.handle();
 7164            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 7165
 7166            fn pop_history(
 7167                editor: &mut Editor,
 7168                cx: &mut MutableAppContext,
 7169            ) -> Option<NavigationEntry> {
 7170                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 7171            }
 7172
 7173            // Move the cursor a small distance.
 7174            // Nothing is added to the navigation history.
 7175            editor.change_selections(None, cx, |s| {
 7176                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 7177            });
 7178            editor.change_selections(None, cx, |s| {
 7179                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 7180            });
 7181            assert!(pop_history(&mut editor, cx).is_none());
 7182
 7183            // Move the cursor a large distance.
 7184            // The history can jump back to the previous position.
 7185            editor.change_selections(None, cx, |s| {
 7186                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 7187            });
 7188            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7189            editor.navigate(nav_entry.data.unwrap(), cx);
 7190            assert_eq!(nav_entry.item.id(), cx.view_id());
 7191            assert_eq!(
 7192                editor.selections.display_ranges(cx),
 7193                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 7194            );
 7195            assert!(pop_history(&mut editor, cx).is_none());
 7196
 7197            // Move the cursor a small distance via the mouse.
 7198            // Nothing is added to the navigation history.
 7199            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 7200            editor.end_selection(cx);
 7201            assert_eq!(
 7202                editor.selections.display_ranges(cx),
 7203                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7204            );
 7205            assert!(pop_history(&mut editor, cx).is_none());
 7206
 7207            // Move the cursor a large distance via the mouse.
 7208            // The history can jump back to the previous position.
 7209            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 7210            editor.end_selection(cx);
 7211            assert_eq!(
 7212                editor.selections.display_ranges(cx),
 7213                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 7214            );
 7215            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7216            editor.navigate(nav_entry.data.unwrap(), cx);
 7217            assert_eq!(nav_entry.item.id(), cx.view_id());
 7218            assert_eq!(
 7219                editor.selections.display_ranges(cx),
 7220                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7221            );
 7222            assert!(pop_history(&mut editor, cx).is_none());
 7223
 7224            // Set scroll position to check later
 7225            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 7226            let original_scroll_position = editor.scroll_position;
 7227            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 7228
 7229            // Jump to the end of the document and adjust scroll
 7230            editor.move_to_end(&MoveToEnd, cx);
 7231            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 7232            assert_ne!(editor.scroll_position, original_scroll_position);
 7233            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7234
 7235            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7236            editor.navigate(nav_entry.data.unwrap(), cx);
 7237            assert_eq!(editor.scroll_position, original_scroll_position);
 7238            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7239
 7240            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 7241            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 7242            invalid_anchor.text_anchor.buffer_id = Some(999);
 7243            let invalid_point = Point::new(9999, 0);
 7244            editor.navigate(
 7245                Box::new(NavigationData {
 7246                    cursor_anchor: invalid_anchor.clone(),
 7247                    cursor_position: invalid_point,
 7248                    scroll_top_anchor: invalid_anchor,
 7249                    scroll_top_row: invalid_point.row,
 7250                    scroll_position: Default::default(),
 7251                }),
 7252                cx,
 7253            );
 7254            assert_eq!(
 7255                editor.selections.display_ranges(cx),
 7256                &[editor.max_point(cx)..editor.max_point(cx)]
 7257            );
 7258            assert_eq!(
 7259                editor.scroll_position(cx),
 7260                vec2f(0., editor.max_point(cx).row() as f32)
 7261            );
 7262
 7263            editor
 7264        });
 7265    }
 7266
 7267    #[gpui::test]
 7268    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 7269        cx.set_global(Settings::test(cx));
 7270        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7271        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7272
 7273        view.update(cx, |view, cx| {
 7274            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 7275            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7276            view.end_selection(cx);
 7277
 7278            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 7279            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 7280            view.end_selection(cx);
 7281            assert_eq!(
 7282                view.selections.display_ranges(cx),
 7283                [
 7284                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 7285                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 7286                ]
 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(3, 4)..DisplayPoint::new(1, 1)]
 7295            );
 7296        });
 7297
 7298        view.update(cx, |view, cx| {
 7299            view.cancel(&Cancel, cx);
 7300            assert_eq!(
 7301                view.selections.display_ranges(cx),
 7302                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 7303            );
 7304        });
 7305    }
 7306
 7307    #[gpui::test]
 7308    fn test_fold(cx: &mut gpui::MutableAppContext) {
 7309        cx.set_global(Settings::test(cx));
 7310        let buffer = MultiBuffer::build_simple(
 7311            &"
 7312                impl Foo {
 7313                    // Hello!
 7314
 7315                    fn a() {
 7316                        1
 7317                    }
 7318
 7319                    fn b() {
 7320                        2
 7321                    }
 7322
 7323                    fn c() {
 7324                        3
 7325                    }
 7326                }
 7327            "
 7328            .unindent(),
 7329            cx,
 7330        );
 7331        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7332
 7333        view.update(cx, |view, cx| {
 7334            view.change_selections(None, cx, |s| {
 7335                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 7336            });
 7337            view.fold(&Fold, cx);
 7338            assert_eq!(
 7339                view.display_text(cx),
 7340                "
 7341                    impl Foo {
 7342                        // Hello!
 7343
 7344                        fn a() {
 7345                            1
 7346                        }
 7347
 7348                        fn b() {…
 7349                        }
 7350
 7351                        fn c() {…
 7352                        }
 7353                    }
 7354                "
 7355                .unindent(),
 7356            );
 7357
 7358            view.fold(&Fold, cx);
 7359            assert_eq!(
 7360                view.display_text(cx),
 7361                "
 7362                    impl Foo {…
 7363                    }
 7364                "
 7365                .unindent(),
 7366            );
 7367
 7368            view.unfold_lines(&UnfoldLines, cx);
 7369            assert_eq!(
 7370                view.display_text(cx),
 7371                "
 7372                    impl Foo {
 7373                        // Hello!
 7374
 7375                        fn a() {
 7376                            1
 7377                        }
 7378
 7379                        fn b() {…
 7380                        }
 7381
 7382                        fn c() {…
 7383                        }
 7384                    }
 7385                "
 7386                .unindent(),
 7387            );
 7388
 7389            view.unfold_lines(&UnfoldLines, cx);
 7390            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7391        });
 7392    }
 7393
 7394    #[gpui::test]
 7395    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7396        cx.set_global(Settings::test(cx));
 7397        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7398        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7399
 7400        buffer.update(cx, |buffer, cx| {
 7401            buffer.edit(
 7402                vec![
 7403                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7404                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7405                ],
 7406                None,
 7407                cx,
 7408            );
 7409        });
 7410
 7411        view.update(cx, |view, cx| {
 7412            assert_eq!(
 7413                view.selections.display_ranges(cx),
 7414                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7415            );
 7416
 7417            view.move_down(&MoveDown, cx);
 7418            assert_eq!(
 7419                view.selections.display_ranges(cx),
 7420                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7421            );
 7422
 7423            view.move_right(&MoveRight, cx);
 7424            assert_eq!(
 7425                view.selections.display_ranges(cx),
 7426                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7427            );
 7428
 7429            view.move_left(&MoveLeft, cx);
 7430            assert_eq!(
 7431                view.selections.display_ranges(cx),
 7432                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7433            );
 7434
 7435            view.move_up(&MoveUp, cx);
 7436            assert_eq!(
 7437                view.selections.display_ranges(cx),
 7438                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7439            );
 7440
 7441            view.move_to_end(&MoveToEnd, cx);
 7442            assert_eq!(
 7443                view.selections.display_ranges(cx),
 7444                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7445            );
 7446
 7447            view.move_to_beginning(&MoveToBeginning, cx);
 7448            assert_eq!(
 7449                view.selections.display_ranges(cx),
 7450                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7451            );
 7452
 7453            view.change_selections(None, cx, |s| {
 7454                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 7455            });
 7456            view.select_to_beginning(&SelectToBeginning, cx);
 7457            assert_eq!(
 7458                view.selections.display_ranges(cx),
 7459                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7460            );
 7461
 7462            view.select_to_end(&SelectToEnd, cx);
 7463            assert_eq!(
 7464                view.selections.display_ranges(cx),
 7465                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7466            );
 7467        });
 7468    }
 7469
 7470    #[gpui::test]
 7471    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7472        cx.set_global(Settings::test(cx));
 7473        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7474        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7475
 7476        assert_eq!('ⓐ'.len_utf8(), 3);
 7477        assert_eq!('α'.len_utf8(), 2);
 7478
 7479        view.update(cx, |view, cx| {
 7480            view.fold_ranges(
 7481                vec![
 7482                    Point::new(0, 6)..Point::new(0, 12),
 7483                    Point::new(1, 2)..Point::new(1, 4),
 7484                    Point::new(2, 4)..Point::new(2, 8),
 7485                ],
 7486                cx,
 7487            );
 7488            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7489
 7490            view.move_right(&MoveRight, cx);
 7491            assert_eq!(
 7492                view.selections.display_ranges(cx),
 7493                &[empty_range(0, "".len())]
 7494            );
 7495            view.move_right(&MoveRight, cx);
 7496            assert_eq!(
 7497                view.selections.display_ranges(cx),
 7498                &[empty_range(0, "ⓐⓑ".len())]
 7499            );
 7500            view.move_right(&MoveRight, cx);
 7501            assert_eq!(
 7502                view.selections.display_ranges(cx),
 7503                &[empty_range(0, "ⓐⓑ…".len())]
 7504            );
 7505
 7506            view.move_down(&MoveDown, cx);
 7507            assert_eq!(
 7508                view.selections.display_ranges(cx),
 7509                &[empty_range(1, "ab…".len())]
 7510            );
 7511            view.move_left(&MoveLeft, cx);
 7512            assert_eq!(
 7513                view.selections.display_ranges(cx),
 7514                &[empty_range(1, "ab".len())]
 7515            );
 7516            view.move_left(&MoveLeft, cx);
 7517            assert_eq!(
 7518                view.selections.display_ranges(cx),
 7519                &[empty_range(1, "a".len())]
 7520            );
 7521
 7522            view.move_down(&MoveDown, cx);
 7523            assert_eq!(
 7524                view.selections.display_ranges(cx),
 7525                &[empty_range(2, "α".len())]
 7526            );
 7527            view.move_right(&MoveRight, cx);
 7528            assert_eq!(
 7529                view.selections.display_ranges(cx),
 7530                &[empty_range(2, "αβ".len())]
 7531            );
 7532            view.move_right(&MoveRight, cx);
 7533            assert_eq!(
 7534                view.selections.display_ranges(cx),
 7535                &[empty_range(2, "αβ…".len())]
 7536            );
 7537            view.move_right(&MoveRight, cx);
 7538            assert_eq!(
 7539                view.selections.display_ranges(cx),
 7540                &[empty_range(2, "αβ…ε".len())]
 7541            );
 7542
 7543            view.move_up(&MoveUp, cx);
 7544            assert_eq!(
 7545                view.selections.display_ranges(cx),
 7546                &[empty_range(1, "ab…e".len())]
 7547            );
 7548            view.move_up(&MoveUp, cx);
 7549            assert_eq!(
 7550                view.selections.display_ranges(cx),
 7551                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7552            );
 7553            view.move_left(&MoveLeft, cx);
 7554            assert_eq!(
 7555                view.selections.display_ranges(cx),
 7556                &[empty_range(0, "ⓐⓑ…".len())]
 7557            );
 7558            view.move_left(&MoveLeft, cx);
 7559            assert_eq!(
 7560                view.selections.display_ranges(cx),
 7561                &[empty_range(0, "ⓐⓑ".len())]
 7562            );
 7563            view.move_left(&MoveLeft, cx);
 7564            assert_eq!(
 7565                view.selections.display_ranges(cx),
 7566                &[empty_range(0, "".len())]
 7567            );
 7568        });
 7569    }
 7570
 7571    #[gpui::test]
 7572    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7573        cx.set_global(Settings::test(cx));
 7574        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7575        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7576        view.update(cx, |view, cx| {
 7577            view.change_selections(None, cx, |s| {
 7578                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7579            });
 7580            view.move_down(&MoveDown, cx);
 7581            assert_eq!(
 7582                view.selections.display_ranges(cx),
 7583                &[empty_range(1, "abcd".len())]
 7584            );
 7585
 7586            view.move_down(&MoveDown, cx);
 7587            assert_eq!(
 7588                view.selections.display_ranges(cx),
 7589                &[empty_range(2, "αβγ".len())]
 7590            );
 7591
 7592            view.move_down(&MoveDown, cx);
 7593            assert_eq!(
 7594                view.selections.display_ranges(cx),
 7595                &[empty_range(3, "abcd".len())]
 7596            );
 7597
 7598            view.move_down(&MoveDown, cx);
 7599            assert_eq!(
 7600                view.selections.display_ranges(cx),
 7601                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7602            );
 7603
 7604            view.move_up(&MoveUp, cx);
 7605            assert_eq!(
 7606                view.selections.display_ranges(cx),
 7607                &[empty_range(3, "abcd".len())]
 7608            );
 7609
 7610            view.move_up(&MoveUp, cx);
 7611            assert_eq!(
 7612                view.selections.display_ranges(cx),
 7613                &[empty_range(2, "αβγ".len())]
 7614            );
 7615        });
 7616    }
 7617
 7618    #[gpui::test]
 7619    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7620        cx.set_global(Settings::test(cx));
 7621        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7622        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7623        view.update(cx, |view, cx| {
 7624            view.change_selections(None, cx, |s| {
 7625                s.select_display_ranges([
 7626                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7627                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7628                ]);
 7629            });
 7630        });
 7631
 7632        view.update(cx, |view, cx| {
 7633            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7634            assert_eq!(
 7635                view.selections.display_ranges(cx),
 7636                &[
 7637                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7638                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7639                ]
 7640            );
 7641        });
 7642
 7643        view.update(cx, |view, cx| {
 7644            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7645            assert_eq!(
 7646                view.selections.display_ranges(cx),
 7647                &[
 7648                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7649                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7650                ]
 7651            );
 7652        });
 7653
 7654        view.update(cx, |view, cx| {
 7655            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7656            assert_eq!(
 7657                view.selections.display_ranges(cx),
 7658                &[
 7659                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7660                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7661                ]
 7662            );
 7663        });
 7664
 7665        view.update(cx, |view, cx| {
 7666            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7667            assert_eq!(
 7668                view.selections.display_ranges(cx),
 7669                &[
 7670                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7671                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7672                ]
 7673            );
 7674        });
 7675
 7676        // Moving to the end of line again is a no-op.
 7677        view.update(cx, |view, cx| {
 7678            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7679            assert_eq!(
 7680                view.selections.display_ranges(cx),
 7681                &[
 7682                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7683                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7684                ]
 7685            );
 7686        });
 7687
 7688        view.update(cx, |view, cx| {
 7689            view.move_left(&MoveLeft, cx);
 7690            view.select_to_beginning_of_line(
 7691                &SelectToBeginningOfLine {
 7692                    stop_at_soft_wraps: true,
 7693                },
 7694                cx,
 7695            );
 7696            assert_eq!(
 7697                view.selections.display_ranges(cx),
 7698                &[
 7699                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7700                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7701                ]
 7702            );
 7703        });
 7704
 7705        view.update(cx, |view, cx| {
 7706            view.select_to_beginning_of_line(
 7707                &SelectToBeginningOfLine {
 7708                    stop_at_soft_wraps: true,
 7709                },
 7710                cx,
 7711            );
 7712            assert_eq!(
 7713                view.selections.display_ranges(cx),
 7714                &[
 7715                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7716                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7717                ]
 7718            );
 7719        });
 7720
 7721        view.update(cx, |view, cx| {
 7722            view.select_to_beginning_of_line(
 7723                &SelectToBeginningOfLine {
 7724                    stop_at_soft_wraps: true,
 7725                },
 7726                cx,
 7727            );
 7728            assert_eq!(
 7729                view.selections.display_ranges(cx),
 7730                &[
 7731                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7732                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7733                ]
 7734            );
 7735        });
 7736
 7737        view.update(cx, |view, cx| {
 7738            view.select_to_end_of_line(
 7739                &SelectToEndOfLine {
 7740                    stop_at_soft_wraps: true,
 7741                },
 7742                cx,
 7743            );
 7744            assert_eq!(
 7745                view.selections.display_ranges(cx),
 7746                &[
 7747                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7748                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7749                ]
 7750            );
 7751        });
 7752
 7753        view.update(cx, |view, cx| {
 7754            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7755            assert_eq!(view.display_text(cx), "ab\n  de");
 7756            assert_eq!(
 7757                view.selections.display_ranges(cx),
 7758                &[
 7759                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7760                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7761                ]
 7762            );
 7763        });
 7764
 7765        view.update(cx, |view, cx| {
 7766            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7767            assert_eq!(view.display_text(cx), "\n");
 7768            assert_eq!(
 7769                view.selections.display_ranges(cx),
 7770                &[
 7771                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7772                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7773                ]
 7774            );
 7775        });
 7776    }
 7777
 7778    #[gpui::test]
 7779    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7780        cx.set_global(Settings::test(cx));
 7781        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7782        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7783        view.update(cx, |view, cx| {
 7784            view.change_selections(None, cx, |s| {
 7785                s.select_display_ranges([
 7786                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7787                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7788                ])
 7789            });
 7790
 7791            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7792            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7793
 7794            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7795            assert_selection_ranges("use stdˇ::str::{foo, bar}\n\n  ˇ{baz.qux()}", view, cx);
 7796
 7797            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7798            assert_selection_ranges("use ˇstd::str::{foo, bar}\n\nˇ  {baz.qux()}", view, cx);
 7799
 7800            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7801            assert_selection_ranges("ˇuse std::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7802
 7803            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7804            assert_selection_ranges("ˇuse std::str::{foo, barˇ}\n\n  {baz.qux()}", view, cx);
 7805
 7806            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7807            assert_selection_ranges("useˇ std::str::{foo, bar}ˇ\n\n  {baz.qux()}", view, cx);
 7808
 7809            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7810            assert_selection_ranges("use stdˇ::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7811
 7812            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7813            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7814
 7815            view.move_right(&MoveRight, cx);
 7816            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7817            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7818
 7819            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7820            assert_selection_ranges("use std«ˇ::s»tr::{foo, bar}\n\n  «ˇ{b»az.qux()}", view, cx);
 7821
 7822            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7823            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7824        });
 7825    }
 7826
 7827    #[gpui::test]
 7828    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7829        cx.set_global(Settings::test(cx));
 7830        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7831        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7832
 7833        view.update(cx, |view, cx| {
 7834            view.set_wrap_width(Some(140.), cx);
 7835            assert_eq!(
 7836                view.display_text(cx),
 7837                "use one::{\n    two::three::\n    four::five\n};"
 7838            );
 7839
 7840            view.change_selections(None, cx, |s| {
 7841                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7842            });
 7843
 7844            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7845            assert_eq!(
 7846                view.selections.display_ranges(cx),
 7847                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7848            );
 7849
 7850            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7851            assert_eq!(
 7852                view.selections.display_ranges(cx),
 7853                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7854            );
 7855
 7856            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7857            assert_eq!(
 7858                view.selections.display_ranges(cx),
 7859                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7860            );
 7861
 7862            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7863            assert_eq!(
 7864                view.selections.display_ranges(cx),
 7865                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7866            );
 7867
 7868            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7869            assert_eq!(
 7870                view.selections.display_ranges(cx),
 7871                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7872            );
 7873
 7874            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7875            assert_eq!(
 7876                view.selections.display_ranges(cx),
 7877                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7878            );
 7879        });
 7880    }
 7881
 7882    #[gpui::test]
 7883    async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) {
 7884        let mut cx = EditorTestContext::new(cx);
 7885        cx.set_state("one «two threeˇ» four");
 7886        cx.update_editor(|editor, cx| {
 7887            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7888            assert_eq!(editor.text(cx), " four");
 7889        });
 7890    }
 7891
 7892    #[gpui::test]
 7893    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7894        cx.set_global(Settings::test(cx));
 7895        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7896        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7897
 7898        view.update(cx, |view, cx| {
 7899            view.change_selections(None, cx, |s| {
 7900                s.select_display_ranges([
 7901                    // an empty selection - the preceding word fragment is deleted
 7902                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7903                    // characters selected - they are deleted
 7904                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7905                ])
 7906            });
 7907            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7908        });
 7909
 7910        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7911
 7912        view.update(cx, |view, cx| {
 7913            view.change_selections(None, cx, |s| {
 7914                s.select_display_ranges([
 7915                    // an empty selection - the following word fragment is deleted
 7916                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7917                    // characters selected - they are deleted
 7918                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7919                ])
 7920            });
 7921            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7922        });
 7923
 7924        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7925    }
 7926
 7927    #[gpui::test]
 7928    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7929        cx.set_global(Settings::test(cx));
 7930        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7931        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7932
 7933        view.update(cx, |view, cx| {
 7934            view.change_selections(None, cx, |s| {
 7935                s.select_display_ranges([
 7936                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7937                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7938                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7939                ])
 7940            });
 7941
 7942            view.newline(&Newline, cx);
 7943            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7944        });
 7945    }
 7946
 7947    #[gpui::test]
 7948    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7949        cx.set_global(Settings::test(cx));
 7950        let buffer = MultiBuffer::build_simple(
 7951            "
 7952                a
 7953                b(
 7954                    X
 7955                )
 7956                c(
 7957                    X
 7958                )
 7959            "
 7960            .unindent()
 7961            .as_str(),
 7962            cx,
 7963        );
 7964
 7965        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7966            let mut editor = build_editor(buffer.clone(), cx);
 7967            editor.change_selections(None, cx, |s| {
 7968                s.select_ranges([
 7969                    Point::new(2, 4)..Point::new(2, 5),
 7970                    Point::new(5, 4)..Point::new(5, 5),
 7971                ])
 7972            });
 7973            editor
 7974        });
 7975
 7976        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7977        buffer.update(cx, |buffer, cx| {
 7978            buffer.edit(
 7979                [
 7980                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7981                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7982                ],
 7983                None,
 7984                cx,
 7985            );
 7986            assert_eq!(
 7987                buffer.read(cx).text(),
 7988                "
 7989                    a
 7990                    b()
 7991                    c()
 7992                "
 7993                .unindent()
 7994            );
 7995        });
 7996
 7997        editor.update(cx, |editor, cx| {
 7998            assert_eq!(
 7999                editor.selections.ranges(cx),
 8000                &[
 8001                    Point::new(1, 2)..Point::new(1, 2),
 8002                    Point::new(2, 2)..Point::new(2, 2),
 8003                ],
 8004            );
 8005
 8006            editor.newline(&Newline, cx);
 8007            assert_eq!(
 8008                editor.text(cx),
 8009                "
 8010                    a
 8011                    b(
 8012                    )
 8013                    c(
 8014                    )
 8015                "
 8016                .unindent()
 8017            );
 8018
 8019            // The selections are moved after the inserted newlines
 8020            assert_eq!(
 8021                editor.selections.ranges(cx),
 8022                &[
 8023                    Point::new(2, 0)..Point::new(2, 0),
 8024                    Point::new(4, 0)..Point::new(4, 0),
 8025                ],
 8026            );
 8027        });
 8028    }
 8029
 8030    #[gpui::test]
 8031    async fn test_newline_below(cx: &mut gpui::TestAppContext) {
 8032        let mut cx = EditorTestContext::new(cx);
 8033        cx.update(|cx| {
 8034            cx.update_global::<Settings, _, _>(|settings, _| {
 8035                settings.editor_overrides.tab_size = Some(NonZeroU32::new(4).unwrap());
 8036            });
 8037        });
 8038
 8039        let language = Arc::new(
 8040            Language::new(
 8041                LanguageConfig::default(),
 8042                Some(tree_sitter_rust::language()),
 8043            )
 8044            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 8045            .unwrap(),
 8046        );
 8047        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8048
 8049        cx.set_state(indoc! {"
 8050            const a: ˇA = (
 8051 8052                    «const_functionˇ»(ˇ),
 8053                    so«mˇ»et«hˇ»ing_ˇelse,ˇ
 8054 8055            ˇ);ˇ
 8056        "});
 8057        cx.update_editor(|e, cx| e.newline_below(&NewlineBelow, cx));
 8058        cx.assert_editor_state(indoc! {"
 8059            const a: A = (
 8060                ˇ
 8061                (
 8062                    ˇ
 8063                    const_function(),
 8064                    ˇ
 8065                    ˇ
 8066                    something_else,
 8067                    ˇ
 8068                    ˇ
 8069                    ˇ
 8070                    ˇ
 8071                )
 8072                ˇ
 8073            );
 8074            ˇ
 8075            ˇ
 8076        "});
 8077    }
 8078
 8079    #[gpui::test]
 8080    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 8081        cx.set_global(Settings::test(cx));
 8082        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 8083        let (_, editor) = cx.add_window(Default::default(), |cx| {
 8084            let mut editor = build_editor(buffer.clone(), cx);
 8085            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 8086            editor
 8087        });
 8088
 8089        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 8090        buffer.update(cx, |buffer, cx| {
 8091            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
 8092            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 8093        });
 8094
 8095        editor.update(cx, |editor, cx| {
 8096            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 8097
 8098            editor.insert("Z", cx);
 8099            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 8100
 8101            // The selections are moved after the inserted characters
 8102            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 8103        });
 8104    }
 8105
 8106    #[gpui::test]
 8107    async fn test_tab(cx: &mut gpui::TestAppContext) {
 8108        let mut cx = EditorTestContext::new(cx);
 8109        cx.update(|cx| {
 8110            cx.update_global::<Settings, _, _>(|settings, _| {
 8111                settings.editor_overrides.tab_size = Some(NonZeroU32::new(3).unwrap());
 8112            });
 8113        });
 8114        cx.set_state(indoc! {"
 8115            ˇabˇc
 8116            ˇ🏀ˇ🏀ˇefg
 8117 8118        "});
 8119        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8120        cx.assert_editor_state(indoc! {"
 8121              ˇab ˇc
 8122              ˇ🏀  ˇ🏀  ˇefg
 8123           d  ˇ
 8124        "});
 8125
 8126        cx.set_state(indoc! {"
 8127            a
 8128            «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8129        "});
 8130        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8131        cx.assert_editor_state(indoc! {"
 8132            a
 8133               «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8134        "});
 8135    }
 8136
 8137    #[gpui::test]
 8138    async fn test_tab_on_blank_line_auto_indents(cx: &mut gpui::TestAppContext) {
 8139        let mut cx = EditorTestContext::new(cx);
 8140        let language = Arc::new(
 8141            Language::new(
 8142                LanguageConfig::default(),
 8143                Some(tree_sitter_rust::language()),
 8144            )
 8145            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 8146            .unwrap(),
 8147        );
 8148        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8149
 8150        // cursors that are already at the suggested indent level insert
 8151        // a soft tab. cursors that are to the left of the suggested indent
 8152        // auto-indent their line.
 8153        cx.set_state(indoc! {"
 8154            ˇ
 8155            const a: B = (
 8156                c(
 8157                    d(
 8158            ˇ
 8159                    )
 8160            ˇ
 8161            ˇ    )
 8162            );
 8163        "});
 8164        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8165        cx.assert_editor_state(indoc! {"
 8166                ˇ
 8167            const a: B = (
 8168                c(
 8169                    d(
 8170                        ˇ
 8171                    )
 8172                    ˇ
 8173                ˇ)
 8174            );
 8175        "});
 8176
 8177        // handle auto-indent when there are multiple cursors on the same line
 8178        cx.set_state(indoc! {"
 8179            const a: B = (
 8180                c(
 8181            ˇ    ˇ    
 8182            ˇ    )
 8183            );
 8184        "});
 8185        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8186        cx.assert_editor_state(indoc! {"
 8187            const a: B = (
 8188                c(
 8189                    ˇ
 8190                ˇ)
 8191            );
 8192        "});
 8193    }
 8194
 8195    #[gpui::test]
 8196    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 8197        let mut cx = EditorTestContext::new(cx);
 8198
 8199        cx.set_state(indoc! {"
 8200              «oneˇ» «twoˇ»
 8201            three
 8202             four
 8203        "});
 8204        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8205        cx.assert_editor_state(indoc! {"
 8206                «oneˇ» «twoˇ»
 8207            three
 8208             four
 8209        "});
 8210
 8211        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8212        cx.assert_editor_state(indoc! {"
 8213            «oneˇ» «twoˇ»
 8214            three
 8215             four
 8216        "});
 8217
 8218        // select across line ending
 8219        cx.set_state(indoc! {"
 8220            one two
 8221            t«hree
 8222            ˇ» four
 8223        "});
 8224        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8225        cx.assert_editor_state(indoc! {"
 8226            one two
 8227                t«hree
 8228            ˇ» four
 8229        "});
 8230
 8231        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8232        cx.assert_editor_state(indoc! {"
 8233            one two
 8234            t«hree
 8235            ˇ» four
 8236        "});
 8237
 8238        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8239        cx.set_state(indoc! {"
 8240            one two
 8241            ˇthree
 8242                four
 8243        "});
 8244        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8245        cx.assert_editor_state(indoc! {"
 8246            one two
 8247                ˇthree
 8248                four
 8249        "});
 8250
 8251        cx.set_state(indoc! {"
 8252            one two
 8253            ˇ    three
 8254             four
 8255        "});
 8256        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8257        cx.assert_editor_state(indoc! {"
 8258            one two
 8259            ˇthree
 8260             four
 8261        "});
 8262    }
 8263
 8264    #[gpui::test]
 8265    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 8266        let mut cx = EditorTestContext::new(cx);
 8267        cx.update(|cx| {
 8268            cx.update_global::<Settings, _, _>(|settings, _| {
 8269                settings.editor_overrides.hard_tabs = Some(true);
 8270            });
 8271        });
 8272
 8273        // select two ranges on one line
 8274        cx.set_state(indoc! {"
 8275            «oneˇ» «twoˇ»
 8276            three
 8277            four
 8278        "});
 8279        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8280        cx.assert_editor_state(indoc! {"
 8281            \t«oneˇ» «twoˇ»
 8282            three
 8283            four
 8284        "});
 8285        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8286        cx.assert_editor_state(indoc! {"
 8287            \t\t«oneˇ» «twoˇ»
 8288            three
 8289            four
 8290        "});
 8291        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8292        cx.assert_editor_state(indoc! {"
 8293            \t«oneˇ» «twoˇ»
 8294            three
 8295            four
 8296        "});
 8297        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8298        cx.assert_editor_state(indoc! {"
 8299            «oneˇ» «twoˇ»
 8300            three
 8301            four
 8302        "});
 8303
 8304        // select across a line ending
 8305        cx.set_state(indoc! {"
 8306            one two
 8307            t«hree
 8308            ˇ»four
 8309        "});
 8310        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8311        cx.assert_editor_state(indoc! {"
 8312            one two
 8313            \tt«hree
 8314            ˇ»four
 8315        "});
 8316        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8317        cx.assert_editor_state(indoc! {"
 8318            one two
 8319            \t\tt«hree
 8320            ˇ»four
 8321        "});
 8322        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8323        cx.assert_editor_state(indoc! {"
 8324            one two
 8325            \tt«hree
 8326            ˇ»four
 8327        "});
 8328        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8329        cx.assert_editor_state(indoc! {"
 8330            one two
 8331            t«hree
 8332            ˇ»four
 8333        "});
 8334
 8335        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8336        cx.set_state(indoc! {"
 8337            one two
 8338            ˇthree
 8339            four
 8340        "});
 8341        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8342        cx.assert_editor_state(indoc! {"
 8343            one two
 8344            ˇthree
 8345            four
 8346        "});
 8347        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8348        cx.assert_editor_state(indoc! {"
 8349            one two
 8350            \tˇthree
 8351            four
 8352        "});
 8353        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8354        cx.assert_editor_state(indoc! {"
 8355            one two
 8356            ˇthree
 8357            four
 8358        "});
 8359    }
 8360
 8361    #[gpui::test]
 8362    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 8363        cx.set_global(
 8364            Settings::test(cx)
 8365                .with_language_defaults(
 8366                    "TOML",
 8367                    EditorSettings {
 8368                        tab_size: Some(2.try_into().unwrap()),
 8369                        ..Default::default()
 8370                    },
 8371                )
 8372                .with_language_defaults(
 8373                    "Rust",
 8374                    EditorSettings {
 8375                        tab_size: Some(4.try_into().unwrap()),
 8376                        ..Default::default()
 8377                    },
 8378                ),
 8379        );
 8380        let toml_language = Arc::new(Language::new(
 8381            LanguageConfig {
 8382                name: "TOML".into(),
 8383                ..Default::default()
 8384            },
 8385            None,
 8386        ));
 8387        let rust_language = Arc::new(Language::new(
 8388            LanguageConfig {
 8389                name: "Rust".into(),
 8390                ..Default::default()
 8391            },
 8392            None,
 8393        ));
 8394
 8395        let toml_buffer = cx
 8396            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 8397        let rust_buffer = cx.add_model(|cx| {
 8398            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 8399        });
 8400        let multibuffer = cx.add_model(|cx| {
 8401            let mut multibuffer = MultiBuffer::new(0);
 8402            multibuffer.push_excerpts(
 8403                toml_buffer.clone(),
 8404                [ExcerptRange {
 8405                    context: Point::new(0, 0)..Point::new(2, 0),
 8406                    primary: None,
 8407                }],
 8408                cx,
 8409            );
 8410            multibuffer.push_excerpts(
 8411                rust_buffer.clone(),
 8412                [ExcerptRange {
 8413                    context: Point::new(0, 0)..Point::new(1, 0),
 8414                    primary: None,
 8415                }],
 8416                cx,
 8417            );
 8418            multibuffer
 8419        });
 8420
 8421        cx.add_window(Default::default(), |cx| {
 8422            let mut editor = build_editor(multibuffer, cx);
 8423
 8424            assert_eq!(
 8425                editor.text(cx),
 8426                indoc! {"
 8427                    a = 1
 8428                    b = 2
 8429
 8430                    const c: usize = 3;
 8431                "}
 8432            );
 8433
 8434            select_ranges(
 8435                &mut editor,
 8436                indoc! {"
 8437                    «aˇ» = 1
 8438                    b = 2
 8439
 8440                    «const c:ˇ» usize = 3;
 8441                "},
 8442                cx,
 8443            );
 8444
 8445            editor.tab(&Tab, cx);
 8446            assert_text_with_selections(
 8447                &mut editor,
 8448                indoc! {"
 8449                      «aˇ» = 1
 8450                    b = 2
 8451
 8452                        «const c:ˇ» usize = 3;
 8453                "},
 8454                cx,
 8455            );
 8456            editor.tab_prev(&TabPrev, cx);
 8457            assert_text_with_selections(
 8458                &mut editor,
 8459                indoc! {"
 8460                    «aˇ» = 1
 8461                    b = 2
 8462
 8463                    «const c:ˇ» usize = 3;
 8464                "},
 8465                cx,
 8466            );
 8467
 8468            editor
 8469        });
 8470    }
 8471
 8472    #[gpui::test]
 8473    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 8474        let mut cx = EditorTestContext::new(cx);
 8475
 8476        // Basic backspace
 8477        cx.set_state(indoc! {"
 8478            onˇe two three
 8479            fou«rˇ» five six
 8480            seven «ˇeight nine
 8481            »ten
 8482        "});
 8483        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8484        cx.assert_editor_state(indoc! {"
 8485            oˇe two three
 8486            fouˇ five six
 8487            seven ˇten
 8488        "});
 8489
 8490        // Test backspace inside and around indents
 8491        cx.set_state(indoc! {"
 8492            zero
 8493                ˇone
 8494                    ˇtwo
 8495                ˇ ˇ ˇ  three
 8496            ˇ  ˇ  four
 8497        "});
 8498        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8499        cx.assert_editor_state(indoc! {"
 8500            zero
 8501            ˇone
 8502                ˇtwo
 8503            ˇ  threeˇ  four
 8504        "});
 8505
 8506        // Test backspace with line_mode set to true
 8507        cx.update_editor(|e, _| e.selections.line_mode = true);
 8508        cx.set_state(indoc! {"
 8509            The ˇquick ˇbrown
 8510            fox jumps over
 8511            the lazy dog
 8512            ˇThe qu«ick bˇ»rown"});
 8513        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8514        cx.assert_editor_state(indoc! {"
 8515            ˇfox jumps over
 8516            the lazy dogˇ"});
 8517    }
 8518
 8519    #[gpui::test]
 8520    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8521        let mut cx = EditorTestContext::new(cx);
 8522
 8523        cx.set_state(indoc! {"
 8524            onˇe two three
 8525            fou«rˇ» five six
 8526            seven «ˇeight nine
 8527            »ten
 8528        "});
 8529        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8530        cx.assert_editor_state(indoc! {"
 8531            onˇ two three
 8532            fouˇ five six
 8533            seven ˇten
 8534        "});
 8535
 8536        // Test backspace with line_mode set to true
 8537        cx.update_editor(|e, _| e.selections.line_mode = true);
 8538        cx.set_state(indoc! {"
 8539            The ˇquick ˇbrown
 8540            fox «ˇjum»ps over
 8541            the lazy dog
 8542            ˇThe qu«ick bˇ»rown"});
 8543        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8544        cx.assert_editor_state("ˇthe lazy dogˇ");
 8545    }
 8546
 8547    #[gpui::test]
 8548    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8549        cx.set_global(Settings::test(cx));
 8550        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8551        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8552        view.update(cx, |view, cx| {
 8553            view.change_selections(None, cx, |s| {
 8554                s.select_display_ranges([
 8555                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8556                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8557                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8558                ])
 8559            });
 8560            view.delete_line(&DeleteLine, cx);
 8561            assert_eq!(view.display_text(cx), "ghi");
 8562            assert_eq!(
 8563                view.selections.display_ranges(cx),
 8564                vec![
 8565                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8566                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8567                ]
 8568            );
 8569        });
 8570
 8571        cx.set_global(Settings::test(cx));
 8572        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8573        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8574        view.update(cx, |view, cx| {
 8575            view.change_selections(None, cx, |s| {
 8576                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8577            });
 8578            view.delete_line(&DeleteLine, cx);
 8579            assert_eq!(view.display_text(cx), "ghi\n");
 8580            assert_eq!(
 8581                view.selections.display_ranges(cx),
 8582                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8583            );
 8584        });
 8585    }
 8586
 8587    #[gpui::test]
 8588    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8589        cx.set_global(Settings::test(cx));
 8590        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8591        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8592        view.update(cx, |view, cx| {
 8593            view.change_selections(None, cx, |s| {
 8594                s.select_display_ranges([
 8595                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8596                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8597                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8598                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8599                ])
 8600            });
 8601            view.duplicate_line(&DuplicateLine, cx);
 8602            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8603            assert_eq!(
 8604                view.selections.display_ranges(cx),
 8605                vec![
 8606                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8607                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8608                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8609                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8610                ]
 8611            );
 8612        });
 8613
 8614        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8615        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8616        view.update(cx, |view, cx| {
 8617            view.change_selections(None, cx, |s| {
 8618                s.select_display_ranges([
 8619                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8620                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8621                ])
 8622            });
 8623            view.duplicate_line(&DuplicateLine, cx);
 8624            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8625            assert_eq!(
 8626                view.selections.display_ranges(cx),
 8627                vec![
 8628                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8629                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8630                ]
 8631            );
 8632        });
 8633    }
 8634
 8635    #[gpui::test]
 8636    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8637        cx.set_global(Settings::test(cx));
 8638        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8639        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8640        view.update(cx, |view, cx| {
 8641            view.fold_ranges(
 8642                vec![
 8643                    Point::new(0, 2)..Point::new(1, 2),
 8644                    Point::new(2, 3)..Point::new(4, 1),
 8645                    Point::new(7, 0)..Point::new(8, 4),
 8646                ],
 8647                cx,
 8648            );
 8649            view.change_selections(None, cx, |s| {
 8650                s.select_display_ranges([
 8651                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8652                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8653                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8654                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8655                ])
 8656            });
 8657            assert_eq!(
 8658                view.display_text(cx),
 8659                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8660            );
 8661
 8662            view.move_line_up(&MoveLineUp, cx);
 8663            assert_eq!(
 8664                view.display_text(cx),
 8665                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8666            );
 8667            assert_eq!(
 8668                view.selections.display_ranges(cx),
 8669                vec![
 8670                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8671                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8672                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8673                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8674                ]
 8675            );
 8676        });
 8677
 8678        view.update(cx, |view, cx| {
 8679            view.move_line_down(&MoveLineDown, cx);
 8680            assert_eq!(
 8681                view.display_text(cx),
 8682                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8683            );
 8684            assert_eq!(
 8685                view.selections.display_ranges(cx),
 8686                vec![
 8687                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8688                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8689                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8690                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8691                ]
 8692            );
 8693        });
 8694
 8695        view.update(cx, |view, cx| {
 8696            view.move_line_down(&MoveLineDown, cx);
 8697            assert_eq!(
 8698                view.display_text(cx),
 8699                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8700            );
 8701            assert_eq!(
 8702                view.selections.display_ranges(cx),
 8703                vec![
 8704                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8705                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8706                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8707                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8708                ]
 8709            );
 8710        });
 8711
 8712        view.update(cx, |view, cx| {
 8713            view.move_line_up(&MoveLineUp, cx);
 8714            assert_eq!(
 8715                view.display_text(cx),
 8716                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8717            );
 8718            assert_eq!(
 8719                view.selections.display_ranges(cx),
 8720                vec![
 8721                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8722                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8723                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8724                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8725                ]
 8726            );
 8727        });
 8728    }
 8729
 8730    #[gpui::test]
 8731    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8732        cx.set_global(Settings::test(cx));
 8733        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8734        let snapshot = buffer.read(cx).snapshot(cx);
 8735        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8736        editor.update(cx, |editor, cx| {
 8737            editor.insert_blocks(
 8738                [BlockProperties {
 8739                    style: BlockStyle::Fixed,
 8740                    position: snapshot.anchor_after(Point::new(2, 0)),
 8741                    disposition: BlockDisposition::Below,
 8742                    height: 1,
 8743                    render: Arc::new(|_| Empty::new().boxed()),
 8744                }],
 8745                cx,
 8746            );
 8747            editor.change_selections(None, cx, |s| {
 8748                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8749            });
 8750            editor.move_line_down(&MoveLineDown, cx);
 8751        });
 8752    }
 8753
 8754    #[gpui::test]
 8755    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8756        cx.set_global(Settings::test(cx));
 8757
 8758        _ = cx
 8759            .add_window(Default::default(), |cx| {
 8760                let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8761
 8762                editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8763                editor.transpose(&Default::default(), cx);
 8764                assert_eq!(editor.text(cx), "bac");
 8765                assert_eq!(editor.selections.ranges(cx), [2..2]);
 8766
 8767                editor.transpose(&Default::default(), cx);
 8768                assert_eq!(editor.text(cx), "bca");
 8769                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8770
 8771                editor.transpose(&Default::default(), cx);
 8772                assert_eq!(editor.text(cx), "bac");
 8773                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8774
 8775                editor
 8776            })
 8777            .1;
 8778
 8779        _ = cx
 8780            .add_window(Default::default(), |cx| {
 8781                let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8782
 8783                editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8784                editor.transpose(&Default::default(), cx);
 8785                assert_eq!(editor.text(cx), "acb\nde");
 8786                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8787
 8788                editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8789                editor.transpose(&Default::default(), cx);
 8790                assert_eq!(editor.text(cx), "acbd\ne");
 8791                assert_eq!(editor.selections.ranges(cx), [5..5]);
 8792
 8793                editor.transpose(&Default::default(), cx);
 8794                assert_eq!(editor.text(cx), "acbde\n");
 8795                assert_eq!(editor.selections.ranges(cx), [6..6]);
 8796
 8797                editor.transpose(&Default::default(), cx);
 8798                assert_eq!(editor.text(cx), "acbd\ne");
 8799                assert_eq!(editor.selections.ranges(cx), [6..6]);
 8800
 8801                editor
 8802            })
 8803            .1;
 8804
 8805        _ = cx
 8806            .add_window(Default::default(), |cx| {
 8807                let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8808
 8809                editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8810                editor.transpose(&Default::default(), cx);
 8811                assert_eq!(editor.text(cx), "bacd\ne");
 8812                assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8813
 8814                editor.transpose(&Default::default(), cx);
 8815                assert_eq!(editor.text(cx), "bcade\n");
 8816                assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8817
 8818                editor.transpose(&Default::default(), cx);
 8819                assert_eq!(editor.text(cx), "bcda\ne");
 8820                assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8821
 8822                editor.transpose(&Default::default(), cx);
 8823                assert_eq!(editor.text(cx), "bcade\n");
 8824                assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8825
 8826                editor.transpose(&Default::default(), cx);
 8827                assert_eq!(editor.text(cx), "bcaed\n");
 8828                assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8829
 8830                editor
 8831            })
 8832            .1;
 8833
 8834        _ = cx
 8835            .add_window(Default::default(), |cx| {
 8836                let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8837
 8838                editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8839                editor.transpose(&Default::default(), cx);
 8840                assert_eq!(editor.text(cx), "🏀🍐✋");
 8841                assert_eq!(editor.selections.ranges(cx), [8..8]);
 8842
 8843                editor.transpose(&Default::default(), cx);
 8844                assert_eq!(editor.text(cx), "🏀✋🍐");
 8845                assert_eq!(editor.selections.ranges(cx), [11..11]);
 8846
 8847                editor.transpose(&Default::default(), cx);
 8848                assert_eq!(editor.text(cx), "🏀🍐✋");
 8849                assert_eq!(editor.selections.ranges(cx), [11..11]);
 8850
 8851                editor
 8852            })
 8853            .1;
 8854    }
 8855
 8856    #[gpui::test]
 8857    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8858        let mut cx = EditorTestContext::new(cx);
 8859
 8860        cx.set_state("«one✅ ˇ»two «three ˇ»four «five ˇ»six ");
 8861        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8862        cx.assert_editor_state("ˇtwo ˇfour ˇsix ");
 8863
 8864        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8865        cx.set_state("two ˇfour ˇsix ˇ");
 8866        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8867        cx.assert_editor_state("two one✅ ˇfour three ˇsix five ˇ");
 8868
 8869        // Paste again but with only two cursors. Since the number of cursors doesn't
 8870        // match the number of slices in the clipboard, the entire clipboard text
 8871        // is pasted at each cursor.
 8872        cx.set_state("ˇtwo one✅ four three six five ˇ");
 8873        cx.update_editor(|e, cx| {
 8874            e.handle_input("( ", cx);
 8875            e.paste(&Paste, cx);
 8876            e.handle_input(") ", cx);
 8877        });
 8878        cx.assert_editor_state(indoc! {"
 8879            ( one✅ 
 8880            three 
 8881            five ) ˇtwo one✅ four three six five ( one✅ 
 8882            three 
 8883            five ) ˇ"});
 8884
 8885        // Cut with three selections, one of which is full-line.
 8886        cx.set_state(indoc! {"
 8887            1«2ˇ»3
 8888            4ˇ567
 8889            «8ˇ»9"});
 8890        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8891        cx.assert_editor_state(indoc! {"
 8892            1ˇ3
 8893            ˇ9"});
 8894
 8895        // Paste with three selections, noticing how the copied selection that was full-line
 8896        // gets inserted before the second cursor.
 8897        cx.set_state(indoc! {"
 8898            1ˇ3
 8899 8900            «oˇ»ne"});
 8901        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8902        cx.assert_editor_state(indoc! {"
 8903            12ˇ3
 8904            4567
 8905 8906            8ˇne"});
 8907
 8908        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8909        cx.set_state(indoc! {"
 8910            The quick brown
 8911            fox juˇmps over
 8912            the lazy dog"});
 8913        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8914        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8915
 8916        // Paste with three selections, noticing how the copied full-line selection is inserted
 8917        // before the empty selections but replaces the selection that is non-empty.
 8918        cx.set_state(indoc! {"
 8919            Tˇhe quick brown
 8920            «foˇ»x jumps over
 8921            tˇhe lazy dog"});
 8922        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8923        cx.assert_editor_state(indoc! {"
 8924            fox jumps over
 8925            Tˇhe quick brown
 8926            fox jumps over
 8927            ˇx jumps over
 8928            fox jumps over
 8929            tˇhe lazy dog"});
 8930    }
 8931
 8932    #[gpui::test]
 8933    async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
 8934        let mut cx = EditorTestContext::new(cx);
 8935        let language = Arc::new(Language::new(
 8936            LanguageConfig::default(),
 8937            Some(tree_sitter_rust::language()),
 8938        ));
 8939        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8940
 8941        // Cut an indented block, without the leading whitespace.
 8942        cx.set_state(indoc! {"
 8943            const a: B = (
 8944                c(),
 8945                «d(
 8946                    e,
 8947                    f
 8948                )ˇ»
 8949            );
 8950        "});
 8951        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8952        cx.assert_editor_state(indoc! {"
 8953            const a: B = (
 8954                c(),
 8955                ˇ
 8956            );
 8957        "});
 8958
 8959        // Paste it at the same position.
 8960        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8961        cx.assert_editor_state(indoc! {"
 8962            const a: B = (
 8963                c(),
 8964                d(
 8965                    e,
 8966                    f
 8967 8968            );
 8969        "});
 8970
 8971        // Paste it at a line with a lower indent level.
 8972        cx.set_state(indoc! {"
 8973            ˇ
 8974            const a: B = (
 8975                c(),
 8976            );
 8977        "});
 8978        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8979        cx.assert_editor_state(indoc! {"
 8980            d(
 8981                e,
 8982                f
 8983 8984            const a: B = (
 8985                c(),
 8986            );
 8987        "});
 8988
 8989        // Cut an indented block, with the leading whitespace.
 8990        cx.set_state(indoc! {"
 8991            const a: B = (
 8992                c(),
 8993            «    d(
 8994                    e,
 8995                    f
 8996                )
 8997            ˇ»);
 8998        "});
 8999        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 9000        cx.assert_editor_state(indoc! {"
 9001            const a: B = (
 9002                c(),
 9003            ˇ);
 9004        "});
 9005
 9006        // Paste it at the same position.
 9007        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9008        cx.assert_editor_state(indoc! {"
 9009            const a: B = (
 9010                c(),
 9011                d(
 9012                    e,
 9013                    f
 9014                )
 9015            ˇ);
 9016        "});
 9017
 9018        // Paste it at a line with a higher indent level.
 9019        cx.set_state(indoc! {"
 9020            const a: B = (
 9021                c(),
 9022                d(
 9023                    e,
 9024 9025                )
 9026            );
 9027        "});
 9028        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9029        cx.assert_editor_state(indoc! {"
 9030            const a: B = (
 9031                c(),
 9032                d(
 9033                    e,
 9034                    f    d(
 9035                        e,
 9036                        f
 9037                    )
 9038            ˇ
 9039                )
 9040            );
 9041        "});
 9042    }
 9043
 9044    #[gpui::test]
 9045    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 9046        cx.set_global(Settings::test(cx));
 9047        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 9048        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9049        view.update(cx, |view, cx| {
 9050            view.select_all(&SelectAll, cx);
 9051            assert_eq!(
 9052                view.selections.display_ranges(cx),
 9053                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 9054            );
 9055        });
 9056    }
 9057
 9058    #[gpui::test]
 9059    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 9060        cx.set_global(Settings::test(cx));
 9061        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 9062        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9063        view.update(cx, |view, cx| {
 9064            view.change_selections(None, cx, |s| {
 9065                s.select_display_ranges([
 9066                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9067                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9068                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9069                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 9070                ])
 9071            });
 9072            view.select_line(&SelectLine, cx);
 9073            assert_eq!(
 9074                view.selections.display_ranges(cx),
 9075                vec![
 9076                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 9077                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 9078                ]
 9079            );
 9080        });
 9081
 9082        view.update(cx, |view, cx| {
 9083            view.select_line(&SelectLine, cx);
 9084            assert_eq!(
 9085                view.selections.display_ranges(cx),
 9086                vec![
 9087                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 9088                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 9089                ]
 9090            );
 9091        });
 9092
 9093        view.update(cx, |view, cx| {
 9094            view.select_line(&SelectLine, cx);
 9095            assert_eq!(
 9096                view.selections.display_ranges(cx),
 9097                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 9098            );
 9099        });
 9100    }
 9101
 9102    #[gpui::test]
 9103    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 9104        cx.set_global(Settings::test(cx));
 9105        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 9106        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9107        view.update(cx, |view, cx| {
 9108            view.fold_ranges(
 9109                vec![
 9110                    Point::new(0, 2)..Point::new(1, 2),
 9111                    Point::new(2, 3)..Point::new(4, 1),
 9112                    Point::new(7, 0)..Point::new(8, 4),
 9113                ],
 9114                cx,
 9115            );
 9116            view.change_selections(None, cx, |s| {
 9117                s.select_display_ranges([
 9118                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9119                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9120                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9121                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9122                ])
 9123            });
 9124            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 9125        });
 9126
 9127        view.update(cx, |view, cx| {
 9128            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9129            assert_eq!(
 9130                view.display_text(cx),
 9131                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 9132            );
 9133            assert_eq!(
 9134                view.selections.display_ranges(cx),
 9135                [
 9136                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 9137                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9138                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 9139                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 9140                ]
 9141            );
 9142        });
 9143
 9144        view.update(cx, |view, cx| {
 9145            view.change_selections(None, cx, |s| {
 9146                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 9147            });
 9148            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9149            assert_eq!(
 9150                view.display_text(cx),
 9151                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 9152            );
 9153            assert_eq!(
 9154                view.selections.display_ranges(cx),
 9155                [
 9156                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 9157                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 9158                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9159                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 9160                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 9161                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 9162                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 9163                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 9164                ]
 9165            );
 9166        });
 9167    }
 9168
 9169    #[gpui::test]
 9170    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 9171        cx.set_global(Settings::test(cx));
 9172        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 9173        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9174
 9175        view.update(cx, |view, cx| {
 9176            view.change_selections(None, cx, |s| {
 9177                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 9178            });
 9179        });
 9180        view.update(cx, |view, cx| {
 9181            view.add_selection_above(&AddSelectionAbove, cx);
 9182            assert_eq!(
 9183                view.selections.display_ranges(cx),
 9184                vec![
 9185                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9186                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9187                ]
 9188            );
 9189        });
 9190
 9191        view.update(cx, |view, cx| {
 9192            view.add_selection_above(&AddSelectionAbove, cx);
 9193            assert_eq!(
 9194                view.selections.display_ranges(cx),
 9195                vec![
 9196                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9197                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9198                ]
 9199            );
 9200        });
 9201
 9202        view.update(cx, |view, cx| {
 9203            view.add_selection_below(&AddSelectionBelow, cx);
 9204            assert_eq!(
 9205                view.selections.display_ranges(cx),
 9206                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9207            );
 9208
 9209            view.undo_selection(&UndoSelection, cx);
 9210            assert_eq!(
 9211                view.selections.display_ranges(cx),
 9212                vec![
 9213                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9214                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9215                ]
 9216            );
 9217
 9218            view.redo_selection(&RedoSelection, cx);
 9219            assert_eq!(
 9220                view.selections.display_ranges(cx),
 9221                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9222            );
 9223        });
 9224
 9225        view.update(cx, |view, cx| {
 9226            view.add_selection_below(&AddSelectionBelow, cx);
 9227            assert_eq!(
 9228                view.selections.display_ranges(cx),
 9229                vec![
 9230                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9231                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9232                ]
 9233            );
 9234        });
 9235
 9236        view.update(cx, |view, cx| {
 9237            view.add_selection_below(&AddSelectionBelow, cx);
 9238            assert_eq!(
 9239                view.selections.display_ranges(cx),
 9240                vec![
 9241                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9242                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9243                ]
 9244            );
 9245        });
 9246
 9247        view.update(cx, |view, cx| {
 9248            view.change_selections(None, cx, |s| {
 9249                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 9250            });
 9251        });
 9252        view.update(cx, |view, cx| {
 9253            view.add_selection_below(&AddSelectionBelow, cx);
 9254            assert_eq!(
 9255                view.selections.display_ranges(cx),
 9256                vec![
 9257                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9258                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9259                ]
 9260            );
 9261        });
 9262
 9263        view.update(cx, |view, cx| {
 9264            view.add_selection_below(&AddSelectionBelow, cx);
 9265            assert_eq!(
 9266                view.selections.display_ranges(cx),
 9267                vec![
 9268                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9269                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9270                ]
 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.add_selection_above(&AddSelectionAbove, cx);
 9284            assert_eq!(
 9285                view.selections.display_ranges(cx),
 9286                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9287            );
 9288        });
 9289
 9290        view.update(cx, |view, cx| {
 9291            view.change_selections(None, cx, |s| {
 9292                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 9293            });
 9294            view.add_selection_below(&AddSelectionBelow, cx);
 9295            assert_eq!(
 9296                view.selections.display_ranges(cx),
 9297                vec![
 9298                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9299                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9300                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9301                ]
 9302            );
 9303        });
 9304
 9305        view.update(cx, |view, cx| {
 9306            view.add_selection_below(&AddSelectionBelow, cx);
 9307            assert_eq!(
 9308                view.selections.display_ranges(cx),
 9309                vec![
 9310                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9311                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9312                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9313                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 9314                ]
 9315            );
 9316        });
 9317
 9318        view.update(cx, |view, cx| {
 9319            view.add_selection_above(&AddSelectionAbove, cx);
 9320            assert_eq!(
 9321                view.selections.display_ranges(cx),
 9322                vec![
 9323                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9324                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9325                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9326                ]
 9327            );
 9328        });
 9329
 9330        view.update(cx, |view, cx| {
 9331            view.change_selections(None, cx, |s| {
 9332                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 9333            });
 9334        });
 9335        view.update(cx, |view, cx| {
 9336            view.add_selection_above(&AddSelectionAbove, cx);
 9337            assert_eq!(
 9338                view.selections.display_ranges(cx),
 9339                vec![
 9340                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 9341                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9342                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9343                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9344                ]
 9345            );
 9346        });
 9347
 9348        view.update(cx, |view, cx| {
 9349            view.add_selection_below(&AddSelectionBelow, cx);
 9350            assert_eq!(
 9351                view.selections.display_ranges(cx),
 9352                vec![
 9353                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9354                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9355                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9356                ]
 9357            );
 9358        });
 9359    }
 9360
 9361    #[gpui::test]
 9362    async fn test_select_next(cx: &mut gpui::TestAppContext) {
 9363        let mut cx = EditorTestContext::new(cx);
 9364        cx.set_state("abc\nˇabc abc\ndefabc\nabc");
 9365
 9366        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9367        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9368
 9369        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9370        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9371
 9372        cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx));
 9373        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9374
 9375        cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx));
 9376        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9377
 9378        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9379        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9380
 9381        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9382        cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9383    }
 9384
 9385    #[gpui::test]
 9386    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 9387        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9388        let language = Arc::new(Language::new(
 9389            LanguageConfig::default(),
 9390            Some(tree_sitter_rust::language()),
 9391        ));
 9392
 9393        let text = r#"
 9394            use mod1::mod2::{mod3, mod4};
 9395
 9396            fn fn_1(param1: bool, param2: &str) {
 9397                let var1 = "text";
 9398            }
 9399        "#
 9400        .unindent();
 9401
 9402        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9403        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9404        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9405        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9406            .await;
 9407
 9408        view.update(cx, |view, cx| {
 9409            view.change_selections(None, cx, |s| {
 9410                s.select_display_ranges([
 9411                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9412                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9413                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9414                ]);
 9415            });
 9416            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9417        });
 9418        assert_eq!(
 9419            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 9420            &[
 9421                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9422                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9423                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9424            ]
 9425        );
 9426
 9427        view.update(cx, |view, cx| {
 9428            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9429        });
 9430        assert_eq!(
 9431            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9432            &[
 9433                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9434                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9435            ]
 9436        );
 9437
 9438        view.update(cx, |view, cx| {
 9439            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9440        });
 9441        assert_eq!(
 9442            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9443            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9444        );
 9445
 9446        // Trying to expand the selected syntax node one more time has no effect.
 9447        view.update(cx, |view, cx| {
 9448            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9449        });
 9450        assert_eq!(
 9451            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9452            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9453        );
 9454
 9455        view.update(cx, |view, cx| {
 9456            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9457        });
 9458        assert_eq!(
 9459            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9460            &[
 9461                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9462                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9463            ]
 9464        );
 9465
 9466        view.update(cx, |view, cx| {
 9467            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9468        });
 9469        assert_eq!(
 9470            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9471            &[
 9472                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9473                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9474                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9475            ]
 9476        );
 9477
 9478        view.update(cx, |view, cx| {
 9479            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9480        });
 9481        assert_eq!(
 9482            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9483            &[
 9484                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9485                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9486                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9487            ]
 9488        );
 9489
 9490        // Trying to shrink the selected syntax node one more time has no effect.
 9491        view.update(cx, |view, cx| {
 9492            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9493        });
 9494        assert_eq!(
 9495            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9496            &[
 9497                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9498                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9499                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9500            ]
 9501        );
 9502
 9503        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9504        // a fold.
 9505        view.update(cx, |view, cx| {
 9506            view.fold_ranges(
 9507                vec![
 9508                    Point::new(0, 21)..Point::new(0, 24),
 9509                    Point::new(3, 20)..Point::new(3, 22),
 9510                ],
 9511                cx,
 9512            );
 9513            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9514        });
 9515        assert_eq!(
 9516            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9517            &[
 9518                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9519                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9520                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9521            ]
 9522        );
 9523    }
 9524
 9525    #[gpui::test]
 9526    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9527        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9528        let language = Arc::new(
 9529            Language::new(
 9530                LanguageConfig {
 9531                    brackets: vec![
 9532                        BracketPair {
 9533                            start: "{".to_string(),
 9534                            end: "}".to_string(),
 9535                            close: false,
 9536                            newline: true,
 9537                        },
 9538                        BracketPair {
 9539                            start: "(".to_string(),
 9540                            end: ")".to_string(),
 9541                            close: false,
 9542                            newline: true,
 9543                        },
 9544                    ],
 9545                    ..Default::default()
 9546                },
 9547                Some(tree_sitter_rust::language()),
 9548            )
 9549            .with_indents_query(
 9550                r#"
 9551                (_ "(" ")" @end) @indent
 9552                (_ "{" "}" @end) @indent
 9553                "#,
 9554            )
 9555            .unwrap(),
 9556        );
 9557
 9558        let text = "fn a() {}";
 9559
 9560        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9561        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9562        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9563        editor
 9564            .condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9565            .await;
 9566
 9567        editor.update(cx, |editor, cx| {
 9568            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 9569            editor.newline(&Newline, cx);
 9570            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9571            assert_eq!(
 9572                editor.selections.ranges(cx),
 9573                &[
 9574                    Point::new(1, 4)..Point::new(1, 4),
 9575                    Point::new(3, 4)..Point::new(3, 4),
 9576                    Point::new(5, 0)..Point::new(5, 0)
 9577                ]
 9578            );
 9579        });
 9580    }
 9581
 9582    #[gpui::test]
 9583    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9584        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9585        let language = Arc::new(Language::new(
 9586            LanguageConfig {
 9587                brackets: vec![
 9588                    BracketPair {
 9589                        start: "{".to_string(),
 9590                        end: "}".to_string(),
 9591                        close: true,
 9592                        newline: true,
 9593                    },
 9594                    BracketPair {
 9595                        start: "/*".to_string(),
 9596                        end: " */".to_string(),
 9597                        close: true,
 9598                        newline: true,
 9599                    },
 9600                    BracketPair {
 9601                        start: "[".to_string(),
 9602                        end: "]".to_string(),
 9603                        close: false,
 9604                        newline: true,
 9605                    },
 9606                ],
 9607                autoclose_before: "})]".to_string(),
 9608                ..Default::default()
 9609            },
 9610            Some(tree_sitter_rust::language()),
 9611        ));
 9612
 9613        let text = r#"
 9614            a
 9615
 9616            /
 9617
 9618        "#
 9619        .unindent();
 9620
 9621        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9622        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9623        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9624        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9625            .await;
 9626
 9627        view.update(cx, |view, cx| {
 9628            view.change_selections(None, cx, |s| {
 9629                s.select_display_ranges([
 9630                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9631                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9632                ])
 9633            });
 9634
 9635            view.handle_input("{", cx);
 9636            view.handle_input("{", cx);
 9637            view.handle_input("{", cx);
 9638            assert_eq!(
 9639                view.text(cx),
 9640                "
 9641                {{{}}}
 9642                {{{}}}
 9643                /
 9644
 9645                "
 9646                .unindent()
 9647            );
 9648
 9649            view.move_right(&MoveRight, cx);
 9650            view.handle_input("}", cx);
 9651            view.handle_input("}", cx);
 9652            view.handle_input("}", cx);
 9653            assert_eq!(
 9654                view.text(cx),
 9655                "
 9656                {{{}}}}
 9657                {{{}}}}
 9658                /
 9659
 9660                "
 9661                .unindent()
 9662            );
 9663
 9664            view.undo(&Undo, cx);
 9665            view.handle_input("/", cx);
 9666            view.handle_input("*", cx);
 9667            assert_eq!(
 9668                view.text(cx),
 9669                "
 9670                /* */
 9671                /* */
 9672                /
 9673
 9674                "
 9675                .unindent()
 9676            );
 9677
 9678            view.undo(&Undo, cx);
 9679            view.change_selections(None, cx, |s| {
 9680                s.select_display_ranges([
 9681                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9682                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9683                ])
 9684            });
 9685            view.handle_input("*", cx);
 9686            assert_eq!(
 9687                view.text(cx),
 9688                "
 9689                a
 9690
 9691                /*
 9692                *
 9693                "
 9694                .unindent()
 9695            );
 9696
 9697            // Don't autoclose if the next character isn't whitespace and isn't
 9698            // listed in the language's "autoclose_before" section.
 9699            view.finalize_last_transaction(cx);
 9700            view.change_selections(None, cx, |s| {
 9701                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 9702            });
 9703            view.handle_input("{", cx);
 9704            assert_eq!(
 9705                view.text(cx),
 9706                "
 9707                {a
 9708
 9709                /*
 9710                *
 9711                "
 9712                .unindent()
 9713            );
 9714
 9715            view.undo(&Undo, cx);
 9716            view.change_selections(None, cx, |s| {
 9717                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 9718            });
 9719            view.handle_input("{", cx);
 9720            assert_eq!(
 9721                view.text(cx),
 9722                "
 9723                {a}
 9724
 9725                /*
 9726                *
 9727                "
 9728                .unindent()
 9729            );
 9730            assert_eq!(
 9731                view.selections.display_ranges(cx),
 9732                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9733            );
 9734
 9735            view.undo(&Undo, cx);
 9736            view.handle_input("[", cx);
 9737            assert_eq!(
 9738                view.text(cx),
 9739                "
 9740                [a]
 9741                
 9742                /*
 9743                *
 9744                "
 9745                .unindent()
 9746            );
 9747            assert_eq!(
 9748                view.selections.display_ranges(cx),
 9749                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9750            );
 9751
 9752            view.undo(&Undo, cx);
 9753            view.change_selections(None, cx, |s| {
 9754                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 9755            });
 9756            view.handle_input("[", cx);
 9757            assert_eq!(
 9758                view.text(cx),
 9759                "
 9760                a[
 9761                
 9762                /*
 9763                *
 9764                "
 9765                .unindent()
 9766            );
 9767            assert_eq!(
 9768                view.selections.display_ranges(cx),
 9769                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9770            );
 9771        });
 9772    }
 9773
 9774    #[gpui::test]
 9775    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9776        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9777        let language = Arc::new(Language::new(
 9778            LanguageConfig {
 9779                brackets: vec![BracketPair {
 9780                    start: "{".to_string(),
 9781                    end: "}".to_string(),
 9782                    close: true,
 9783                    newline: true,
 9784                }],
 9785                ..Default::default()
 9786            },
 9787            Some(tree_sitter_rust::language()),
 9788        ));
 9789
 9790        let text = r#"
 9791            a
 9792            b
 9793            c
 9794        "#
 9795        .unindent();
 9796
 9797        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9798        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9799        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9800        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9801            .await;
 9802
 9803        view.update(cx, |view, cx| {
 9804            view.change_selections(None, cx, |s| {
 9805                s.select_display_ranges([
 9806                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9807                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9808                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9809                ])
 9810            });
 9811
 9812            view.handle_input("{", cx);
 9813            view.handle_input("{", cx);
 9814            view.handle_input("{", cx);
 9815            assert_eq!(
 9816                view.text(cx),
 9817                "
 9818                {{{a}}}
 9819                {{{b}}}
 9820                {{{c}}}
 9821                "
 9822                .unindent()
 9823            );
 9824            assert_eq!(
 9825                view.selections.display_ranges(cx),
 9826                [
 9827                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9828                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9829                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9830                ]
 9831            );
 9832
 9833            view.undo(&Undo, cx);
 9834            assert_eq!(
 9835                view.text(cx),
 9836                "
 9837                a
 9838                b
 9839                c
 9840                "
 9841                .unindent()
 9842            );
 9843            assert_eq!(
 9844                view.selections.display_ranges(cx),
 9845                [
 9846                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9847                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9848                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9849                ]
 9850            );
 9851        });
 9852    }
 9853
 9854    #[gpui::test]
 9855    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9856        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9857        let language = Arc::new(Language::new(
 9858            LanguageConfig {
 9859                brackets: vec![BracketPair {
 9860                    start: "{".to_string(),
 9861                    end: "}".to_string(),
 9862                    close: true,
 9863                    newline: true,
 9864                }],
 9865                autoclose_before: "}".to_string(),
 9866                ..Default::default()
 9867            },
 9868            Some(tree_sitter_rust::language()),
 9869        ));
 9870
 9871        let text = r#"
 9872            a
 9873            b
 9874            c
 9875        "#
 9876        .unindent();
 9877
 9878        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9879        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9880        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9881        editor
 9882            .condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9883            .await;
 9884
 9885        editor.update(cx, |editor, cx| {
 9886            editor.change_selections(None, cx, |s| {
 9887                s.select_ranges([
 9888                    Point::new(0, 1)..Point::new(0, 1),
 9889                    Point::new(1, 1)..Point::new(1, 1),
 9890                    Point::new(2, 1)..Point::new(2, 1),
 9891                ])
 9892            });
 9893
 9894            editor.handle_input("{", cx);
 9895            editor.handle_input("{", cx);
 9896            editor.handle_input("_", cx);
 9897            assert_eq!(
 9898                editor.text(cx),
 9899                "
 9900                a{{_}}
 9901                b{{_}}
 9902                c{{_}}
 9903                "
 9904                .unindent()
 9905            );
 9906            assert_eq!(
 9907                editor.selections.ranges::<Point>(cx),
 9908                [
 9909                    Point::new(0, 4)..Point::new(0, 4),
 9910                    Point::new(1, 4)..Point::new(1, 4),
 9911                    Point::new(2, 4)..Point::new(2, 4)
 9912                ]
 9913            );
 9914
 9915            editor.backspace(&Default::default(), cx);
 9916            editor.backspace(&Default::default(), cx);
 9917            assert_eq!(
 9918                editor.text(cx),
 9919                "
 9920                a{}
 9921                b{}
 9922                c{}
 9923                "
 9924                .unindent()
 9925            );
 9926            assert_eq!(
 9927                editor.selections.ranges::<Point>(cx),
 9928                [
 9929                    Point::new(0, 2)..Point::new(0, 2),
 9930                    Point::new(1, 2)..Point::new(1, 2),
 9931                    Point::new(2, 2)..Point::new(2, 2)
 9932                ]
 9933            );
 9934
 9935            editor.delete_to_previous_word_start(&Default::default(), cx);
 9936            assert_eq!(
 9937                editor.text(cx),
 9938                "
 9939                a
 9940                b
 9941                c
 9942                "
 9943                .unindent()
 9944            );
 9945            assert_eq!(
 9946                editor.selections.ranges::<Point>(cx),
 9947                [
 9948                    Point::new(0, 1)..Point::new(0, 1),
 9949                    Point::new(1, 1)..Point::new(1, 1),
 9950                    Point::new(2, 1)..Point::new(2, 1)
 9951                ]
 9952            );
 9953        });
 9954    }
 9955
 9956    #[gpui::test]
 9957    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9958        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9959
 9960        let (text, insertion_ranges) = marked_text_ranges(
 9961            indoc! {"
 9962                a.ˇ b
 9963                a.ˇ b
 9964                a.ˇ b
 9965            "},
 9966            false,
 9967        );
 9968
 9969        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9970        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9971
 9972        editor.update(cx, |editor, cx| {
 9973            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9974
 9975            editor
 9976                .insert_snippet(&insertion_ranges, snippet, cx)
 9977                .unwrap();
 9978
 9979            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text: &str) {
 9980                let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
 9981                assert_eq!(editor.text(cx), expected_text);
 9982                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9983            }
 9984
 9985            assert(
 9986                editor,
 9987                cx,
 9988                indoc! {"
 9989                    a.f(«one», two, «three») b
 9990                    a.f(«one», two, «three») b
 9991                    a.f(«one», two, «three») b
 9992                "},
 9993            );
 9994
 9995            // Can't move earlier than the first tab stop
 9996            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9997            assert(
 9998                editor,
 9999                cx,
10000                indoc! {"
10001                    a.f(«one», two, «three») b
10002                    a.f(«one», two, «three») b
10003                    a.f(«one», two, «three») b
10004                "},
10005            );
10006
10007            assert!(editor.move_to_next_snippet_tabstop(cx));
10008            assert(
10009                editor,
10010                cx,
10011                indoc! {"
10012                    a.f(one, «two», three) b
10013                    a.f(one, «two», three) b
10014                    a.f(one, «two», three) b
10015                "},
10016            );
10017
10018            editor.move_to_prev_snippet_tabstop(cx);
10019            assert(
10020                editor,
10021                cx,
10022                indoc! {"
10023                    a.f(«one», two, «three») b
10024                    a.f(«one», two, «three») b
10025                    a.f(«one», two, «three») b
10026                "},
10027            );
10028
10029            assert!(editor.move_to_next_snippet_tabstop(cx));
10030            assert(
10031                editor,
10032                cx,
10033                indoc! {"
10034                    a.f(one, «two», three) b
10035                    a.f(one, «two», three) b
10036                    a.f(one, «two», three) b
10037                "},
10038            );
10039            assert!(editor.move_to_next_snippet_tabstop(cx));
10040            assert(
10041                editor,
10042                cx,
10043                indoc! {"
10044                    a.f(one, two, three)ˇ b
10045                    a.f(one, two, three)ˇ b
10046                    a.f(one, two, three)ˇ b
10047                "},
10048            );
10049
10050            // As soon as the last tab stop is reached, snippet state is gone
10051            editor.move_to_prev_snippet_tabstop(cx);
10052            assert(
10053                editor,
10054                cx,
10055                indoc! {"
10056                    a.f(one, two, three)ˇ b
10057                    a.f(one, two, three)ˇ b
10058                    a.f(one, two, three)ˇ b
10059                "},
10060            );
10061        });
10062    }
10063
10064    #[gpui::test]
10065    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
10066        cx.foreground().forbid_parking();
10067
10068        let mut language = Language::new(
10069            LanguageConfig {
10070                name: "Rust".into(),
10071                path_suffixes: vec!["rs".to_string()],
10072                ..Default::default()
10073            },
10074            Some(tree_sitter_rust::language()),
10075        );
10076        let mut fake_servers = language
10077            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10078                capabilities: lsp::ServerCapabilities {
10079                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
10080                    ..Default::default()
10081                },
10082                ..Default::default()
10083            }))
10084            .await;
10085
10086        let fs = FakeFs::new(cx.background());
10087        fs.insert_file("/file.rs", Default::default()).await;
10088
10089        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10090        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10091        let buffer = project
10092            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10093            .await
10094            .unwrap();
10095
10096        cx.foreground().start_waiting();
10097        let fake_server = fake_servers.next().await.unwrap();
10098
10099        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10100        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10101        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10102        assert!(cx.read(|cx| editor.is_dirty(cx)));
10103
10104        let save = cx.update(|cx| editor.save(project.clone(), cx));
10105        fake_server
10106            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10107                assert_eq!(
10108                    params.text_document.uri,
10109                    lsp::Url::from_file_path("/file.rs").unwrap()
10110                );
10111                assert_eq!(params.options.tab_size, 4);
10112                Ok(Some(vec![lsp::TextEdit::new(
10113                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10114                    ", ".to_string(),
10115                )]))
10116            })
10117            .next()
10118            .await;
10119        cx.foreground().start_waiting();
10120        save.await.unwrap();
10121        assert_eq!(
10122            editor.read_with(cx, |editor, cx| editor.text(cx)),
10123            "one, two\nthree\n"
10124        );
10125        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10126
10127        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10128        assert!(cx.read(|cx| editor.is_dirty(cx)));
10129
10130        // Ensure we can still save even if formatting hangs.
10131        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10132            assert_eq!(
10133                params.text_document.uri,
10134                lsp::Url::from_file_path("/file.rs").unwrap()
10135            );
10136            futures::future::pending::<()>().await;
10137            unreachable!()
10138        });
10139        let save = cx.update(|cx| editor.save(project.clone(), cx));
10140        cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
10141        cx.foreground().start_waiting();
10142        save.await.unwrap();
10143        assert_eq!(
10144            editor.read_with(cx, |editor, cx| editor.text(cx)),
10145            "one\ntwo\nthree\n"
10146        );
10147        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10148
10149        // Set rust language override and assert overriden tabsize is sent to language server
10150        cx.update(|cx| {
10151            cx.update_global::<Settings, _, _>(|settings, _| {
10152                settings.language_overrides.insert(
10153                    "Rust".into(),
10154                    EditorSettings {
10155                        tab_size: Some(8.try_into().unwrap()),
10156                        ..Default::default()
10157                    },
10158                );
10159            })
10160        });
10161
10162        let save = cx.update(|cx| editor.save(project.clone(), cx));
10163        fake_server
10164            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10165                assert_eq!(
10166                    params.text_document.uri,
10167                    lsp::Url::from_file_path("/file.rs").unwrap()
10168                );
10169                assert_eq!(params.options.tab_size, 8);
10170                Ok(Some(vec![]))
10171            })
10172            .next()
10173            .await;
10174        cx.foreground().start_waiting();
10175        save.await.unwrap();
10176    }
10177
10178    #[gpui::test]
10179    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
10180        cx.foreground().forbid_parking();
10181
10182        let mut language = Language::new(
10183            LanguageConfig {
10184                name: "Rust".into(),
10185                path_suffixes: vec!["rs".to_string()],
10186                ..Default::default()
10187            },
10188            Some(tree_sitter_rust::language()),
10189        );
10190        let mut fake_servers = language
10191            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10192                capabilities: lsp::ServerCapabilities {
10193                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
10194                    ..Default::default()
10195                },
10196                ..Default::default()
10197            }))
10198            .await;
10199
10200        let fs = FakeFs::new(cx.background());
10201        fs.insert_file("/file.rs", Default::default()).await;
10202
10203        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10204        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10205        let buffer = project
10206            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10207            .await
10208            .unwrap();
10209
10210        cx.foreground().start_waiting();
10211        let fake_server = fake_servers.next().await.unwrap();
10212
10213        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10214        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10215        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10216        assert!(cx.read(|cx| editor.is_dirty(cx)));
10217
10218        let save = cx.update(|cx| editor.save(project.clone(), cx));
10219        fake_server
10220            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10221                assert_eq!(
10222                    params.text_document.uri,
10223                    lsp::Url::from_file_path("/file.rs").unwrap()
10224                );
10225                assert_eq!(params.options.tab_size, 4);
10226                Ok(Some(vec![lsp::TextEdit::new(
10227                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10228                    ", ".to_string(),
10229                )]))
10230            })
10231            .next()
10232            .await;
10233        cx.foreground().start_waiting();
10234        save.await.unwrap();
10235        assert_eq!(
10236            editor.read_with(cx, |editor, cx| editor.text(cx)),
10237            "one, two\nthree\n"
10238        );
10239        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10240
10241        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10242        assert!(cx.read(|cx| editor.is_dirty(cx)));
10243
10244        // Ensure we can still save even if formatting hangs.
10245        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
10246            move |params, _| async move {
10247                assert_eq!(
10248                    params.text_document.uri,
10249                    lsp::Url::from_file_path("/file.rs").unwrap()
10250                );
10251                futures::future::pending::<()>().await;
10252                unreachable!()
10253            },
10254        );
10255        let save = cx.update(|cx| editor.save(project.clone(), cx));
10256        cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
10257        cx.foreground().start_waiting();
10258        save.await.unwrap();
10259        assert_eq!(
10260            editor.read_with(cx, |editor, cx| editor.text(cx)),
10261            "one\ntwo\nthree\n"
10262        );
10263        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10264
10265        // Set rust language override and assert overriden tabsize is sent to language server
10266        cx.update(|cx| {
10267            cx.update_global::<Settings, _, _>(|settings, _| {
10268                settings.language_overrides.insert(
10269                    "Rust".into(),
10270                    EditorSettings {
10271                        tab_size: Some(8.try_into().unwrap()),
10272                        ..Default::default()
10273                    },
10274                );
10275            })
10276        });
10277
10278        let save = cx.update(|cx| editor.save(project.clone(), cx));
10279        fake_server
10280            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10281                assert_eq!(
10282                    params.text_document.uri,
10283                    lsp::Url::from_file_path("/file.rs").unwrap()
10284                );
10285                assert_eq!(params.options.tab_size, 8);
10286                Ok(Some(vec![]))
10287            })
10288            .next()
10289            .await;
10290        cx.foreground().start_waiting();
10291        save.await.unwrap();
10292    }
10293
10294    #[gpui::test]
10295    async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
10296        cx.foreground().forbid_parking();
10297
10298        let mut language = Language::new(
10299            LanguageConfig {
10300                name: "Rust".into(),
10301                path_suffixes: vec!["rs".to_string()],
10302                ..Default::default()
10303            },
10304            Some(tree_sitter_rust::language()),
10305        );
10306        let mut fake_servers = language
10307            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10308                capabilities: lsp::ServerCapabilities {
10309                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
10310                    ..Default::default()
10311                },
10312                ..Default::default()
10313            }))
10314            .await;
10315
10316        let fs = FakeFs::new(cx.background());
10317        fs.insert_file("/file.rs", Default::default()).await;
10318
10319        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10320        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10321        let buffer = project
10322            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10323            .await
10324            .unwrap();
10325
10326        cx.foreground().start_waiting();
10327        let fake_server = fake_servers.next().await.unwrap();
10328
10329        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10330        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10331        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10332
10333        let format = editor.update(cx, |editor, cx| editor.perform_format(project.clone(), cx));
10334        fake_server
10335            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10336                assert_eq!(
10337                    params.text_document.uri,
10338                    lsp::Url::from_file_path("/file.rs").unwrap()
10339                );
10340                assert_eq!(params.options.tab_size, 4);
10341                Ok(Some(vec![lsp::TextEdit::new(
10342                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10343                    ", ".to_string(),
10344                )]))
10345            })
10346            .next()
10347            .await;
10348        cx.foreground().start_waiting();
10349        format.await.unwrap();
10350        assert_eq!(
10351            editor.read_with(cx, |editor, cx| editor.text(cx)),
10352            "one, two\nthree\n"
10353        );
10354
10355        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10356        // Ensure we don't lock if formatting hangs.
10357        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10358            assert_eq!(
10359                params.text_document.uri,
10360                lsp::Url::from_file_path("/file.rs").unwrap()
10361            );
10362            futures::future::pending::<()>().await;
10363            unreachable!()
10364        });
10365        let format = editor.update(cx, |editor, cx| editor.perform_format(project, cx));
10366        cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
10367        cx.foreground().start_waiting();
10368        format.await.unwrap();
10369        assert_eq!(
10370            editor.read_with(cx, |editor, cx| editor.text(cx)),
10371            "one\ntwo\nthree\n"
10372        );
10373    }
10374
10375    #[gpui::test]
10376    async fn test_completion(cx: &mut gpui::TestAppContext) {
10377        let mut cx = EditorLspTestContext::new_rust(
10378            lsp::ServerCapabilities {
10379                completion_provider: Some(lsp::CompletionOptions {
10380                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
10381                    ..Default::default()
10382                }),
10383                ..Default::default()
10384            },
10385            cx,
10386        )
10387        .await;
10388
10389        cx.set_state(indoc! {"
10390            oneˇ
10391            two
10392            three
10393        "});
10394        cx.simulate_keystroke(".");
10395        handle_completion_request(
10396            &mut cx,
10397            indoc! {"
10398                one.|<>
10399                two
10400                three
10401            "},
10402            vec!["first_completion", "second_completion"],
10403        )
10404        .await;
10405        cx.condition(|editor, _| editor.context_menu_visible())
10406            .await;
10407        let apply_additional_edits = cx.update_editor(|editor, cx| {
10408            editor.move_down(&MoveDown, cx);
10409            editor
10410                .confirm_completion(&ConfirmCompletion::default(), cx)
10411                .unwrap()
10412        });
10413        cx.assert_editor_state(indoc! {"
10414            one.second_completionˇ
10415            two
10416            three
10417        "});
10418
10419        handle_resolve_completion_request(
10420            &mut cx,
10421            Some((
10422                indoc! {"
10423                    one.second_completion
10424                    two
10425                    threeˇ
10426                "},
10427                "\nadditional edit",
10428            )),
10429        )
10430        .await;
10431        apply_additional_edits.await.unwrap();
10432        cx.assert_editor_state(indoc! {"
10433            one.second_completionˇ
10434            two
10435            three
10436            additional edit
10437        "});
10438
10439        cx.set_state(indoc! {"
10440            one.second_completion
10441            twoˇ
10442            threeˇ
10443            additional edit
10444        "});
10445        cx.simulate_keystroke(" ");
10446        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10447        cx.simulate_keystroke("s");
10448        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10449
10450        cx.assert_editor_state(indoc! {"
10451            one.second_completion
10452            two sˇ
10453            three sˇ
10454            additional edit
10455        "});
10456        //
10457        handle_completion_request(
10458            &mut cx,
10459            indoc! {"
10460                one.second_completion
10461                two s
10462                three <s|>
10463                additional edit
10464            "},
10465            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10466        )
10467        .await;
10468        cx.condition(|editor, _| editor.context_menu_visible())
10469            .await;
10470
10471        cx.simulate_keystroke("i");
10472
10473        handle_completion_request(
10474            &mut cx,
10475            indoc! {"
10476                one.second_completion
10477                two si
10478                three <si|>
10479                additional edit
10480            "},
10481            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10482        )
10483        .await;
10484        cx.condition(|editor, _| editor.context_menu_visible())
10485            .await;
10486
10487        let apply_additional_edits = cx.update_editor(|editor, cx| {
10488            editor
10489                .confirm_completion(&ConfirmCompletion::default(), cx)
10490                .unwrap()
10491        });
10492        cx.assert_editor_state(indoc! {"
10493            one.second_completion
10494            two sixth_completionˇ
10495            three sixth_completionˇ
10496            additional edit
10497        "});
10498
10499        handle_resolve_completion_request(&mut cx, None).await;
10500        apply_additional_edits.await.unwrap();
10501
10502        cx.update(|cx| {
10503            cx.update_global::<Settings, _, _>(|settings, _| {
10504                settings.show_completions_on_input = false;
10505            })
10506        });
10507        cx.set_state("editorˇ");
10508        cx.simulate_keystroke(".");
10509        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10510        cx.simulate_keystroke("c");
10511        cx.simulate_keystroke("l");
10512        cx.simulate_keystroke("o");
10513        cx.assert_editor_state("editor.cloˇ");
10514        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10515        cx.update_editor(|editor, cx| {
10516            editor.show_completions(&ShowCompletions, cx);
10517        });
10518        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
10519        cx.condition(|editor, _| editor.context_menu_visible())
10520            .await;
10521        let apply_additional_edits = cx.update_editor(|editor, cx| {
10522            editor
10523                .confirm_completion(&ConfirmCompletion::default(), cx)
10524                .unwrap()
10525        });
10526        cx.assert_editor_state("editor.closeˇ");
10527        handle_resolve_completion_request(&mut cx, None).await;
10528        apply_additional_edits.await.unwrap();
10529
10530        // Handle completion request passing a marked string specifying where the completion
10531        // should be triggered from using '|' character, what range should be replaced, and what completions
10532        // should be returned using '<' and '>' to delimit the range
10533        async fn handle_completion_request<'a>(
10534            cx: &mut EditorLspTestContext<'a>,
10535            marked_string: &str,
10536            completions: Vec<&'static str>,
10537        ) {
10538            let complete_from_marker: TextRangeMarker = '|'.into();
10539            let replace_range_marker: TextRangeMarker = ('<', '>').into();
10540            let (_, mut marked_ranges) = marked_text_ranges_by(
10541                marked_string,
10542                vec![complete_from_marker.clone(), replace_range_marker.clone()],
10543            );
10544
10545            let complete_from_position =
10546                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
10547            let replace_range =
10548                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10549
10550            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
10551                let completions = completions.clone();
10552                async move {
10553                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
10554                    assert_eq!(
10555                        params.text_document_position.position,
10556                        complete_from_position
10557                    );
10558                    Ok(Some(lsp::CompletionResponse::Array(
10559                        completions
10560                            .iter()
10561                            .map(|completion_text| lsp::CompletionItem {
10562                                label: completion_text.to_string(),
10563                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
10564                                    range: replace_range,
10565                                    new_text: completion_text.to_string(),
10566                                })),
10567                                ..Default::default()
10568                            })
10569                            .collect(),
10570                    )))
10571                }
10572            })
10573            .next()
10574            .await;
10575        }
10576
10577        async fn handle_resolve_completion_request<'a>(
10578            cx: &mut EditorLspTestContext<'a>,
10579            edit: Option<(&'static str, &'static str)>,
10580        ) {
10581            let edit = edit.map(|(marked_string, new_text)| {
10582                let (_, marked_ranges) = marked_text_ranges(marked_string, false);
10583                let replace_range = cx.to_lsp_range(marked_ranges[0].clone());
10584                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
10585            });
10586
10587            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
10588                let edit = edit.clone();
10589                async move {
10590                    Ok(lsp::CompletionItem {
10591                        additional_text_edits: edit,
10592                        ..Default::default()
10593                    })
10594                }
10595            })
10596            .next()
10597            .await;
10598        }
10599    }
10600
10601    #[gpui::test]
10602    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
10603        cx.update(|cx| cx.set_global(Settings::test(cx)));
10604        let language = Arc::new(Language::new(
10605            LanguageConfig {
10606                line_comment: Some("// ".to_string()),
10607                ..Default::default()
10608            },
10609            Some(tree_sitter_rust::language()),
10610        ));
10611
10612        let text = "
10613            fn a() {
10614                //b();
10615                // c();
10616                //  d();
10617            }
10618        "
10619        .unindent();
10620
10621        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10622        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10623        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10624
10625        view.update(cx, |editor, cx| {
10626            // If multiple selections intersect a line, the line is only
10627            // toggled once.
10628            editor.change_selections(None, cx, |s| {
10629                s.select_display_ranges([
10630                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
10631                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
10632                ])
10633            });
10634            editor.toggle_comments(&ToggleComments, cx);
10635            assert_eq!(
10636                editor.text(cx),
10637                "
10638                    fn a() {
10639                        b();
10640                        c();
10641                         d();
10642                    }
10643                "
10644                .unindent()
10645            );
10646
10647            // The comment prefix is inserted at the same column for every line
10648            // in a selection.
10649            editor.change_selections(None, cx, |s| {
10650                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
10651            });
10652            editor.toggle_comments(&ToggleComments, cx);
10653            assert_eq!(
10654                editor.text(cx),
10655                "
10656                    fn a() {
10657                        // b();
10658                        // c();
10659                        //  d();
10660                    }
10661                "
10662                .unindent()
10663            );
10664
10665            // If a selection ends at the beginning of a line, that line is not toggled.
10666            editor.change_selections(None, cx, |s| {
10667                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
10668            });
10669            editor.toggle_comments(&ToggleComments, cx);
10670            assert_eq!(
10671                editor.text(cx),
10672                "
10673                        fn a() {
10674                            // b();
10675                            c();
10676                            //  d();
10677                        }
10678                    "
10679                .unindent()
10680            );
10681        });
10682    }
10683
10684    #[gpui::test]
10685    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
10686        cx.set_global(Settings::test(cx));
10687        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10688        let multibuffer = cx.add_model(|cx| {
10689            let mut multibuffer = MultiBuffer::new(0);
10690            multibuffer.push_excerpts(
10691                buffer.clone(),
10692                [
10693                    ExcerptRange {
10694                        context: Point::new(0, 0)..Point::new(0, 4),
10695                        primary: None,
10696                    },
10697                    ExcerptRange {
10698                        context: Point::new(1, 0)..Point::new(1, 4),
10699                        primary: None,
10700                    },
10701                ],
10702                cx,
10703            );
10704            multibuffer
10705        });
10706
10707        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
10708
10709        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10710        view.update(cx, |view, cx| {
10711            assert_eq!(view.text(cx), "aaaa\nbbbb");
10712            view.change_selections(None, cx, |s| {
10713                s.select_ranges([
10714                    Point::new(0, 0)..Point::new(0, 0),
10715                    Point::new(1, 0)..Point::new(1, 0),
10716                ])
10717            });
10718
10719            view.handle_input("X", cx);
10720            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
10721            assert_eq!(
10722                view.selections.ranges(cx),
10723                [
10724                    Point::new(0, 1)..Point::new(0, 1),
10725                    Point::new(1, 1)..Point::new(1, 1),
10726                ]
10727            )
10728        });
10729    }
10730
10731    #[gpui::test]
10732    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
10733        cx.set_global(Settings::test(cx));
10734        let markers = vec![('[', ']').into(), ('(', ')').into()];
10735        let (initial_text, mut excerpt_ranges) = marked_text_ranges_by(
10736            indoc! {"
10737                [aaaa
10738                (bbbb]
10739                cccc)",
10740            },
10741            markers.clone(),
10742        );
10743        let excerpt_ranges = markers.into_iter().map(|marker| {
10744            let context = excerpt_ranges.remove(&marker).unwrap()[0].clone();
10745            ExcerptRange {
10746                context,
10747                primary: None,
10748            }
10749        });
10750        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
10751        let multibuffer = cx.add_model(|cx| {
10752            let mut multibuffer = MultiBuffer::new(0);
10753            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
10754            multibuffer
10755        });
10756
10757        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
10758        view.update(cx, |view, cx| {
10759            let (expected_text, selection_ranges) = marked_text_ranges(
10760                indoc! {"
10761                    aaaa
10762                    bˇbbb
10763                    bˇbbˇb
10764                    cccc"
10765                },
10766                true,
10767            );
10768            assert_eq!(view.text(cx), expected_text);
10769            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
10770
10771            view.handle_input("X", cx);
10772
10773            let (expected_text, expected_selections) = marked_text_ranges(
10774                indoc! {"
10775                    aaaa
10776                    bXˇbbXb
10777                    bXˇbbXˇb
10778                    cccc"
10779                },
10780                false,
10781            );
10782            assert_eq!(view.text(cx), expected_text);
10783            assert_eq!(view.selections.ranges(cx), expected_selections);
10784
10785            view.newline(&Newline, cx);
10786            let (expected_text, expected_selections) = marked_text_ranges(
10787                indoc! {"
10788                    aaaa
10789                    bX
10790                    ˇbbX
10791                    b
10792                    bX
10793                    ˇbbX
10794                    ˇb
10795                    cccc"
10796                },
10797                false,
10798            );
10799            assert_eq!(view.text(cx), expected_text);
10800            assert_eq!(view.selections.ranges(cx), expected_selections);
10801        });
10802    }
10803
10804    #[gpui::test]
10805    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
10806        cx.set_global(Settings::test(cx));
10807        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10808        let mut excerpt1_id = None;
10809        let multibuffer = cx.add_model(|cx| {
10810            let mut multibuffer = MultiBuffer::new(0);
10811            excerpt1_id = multibuffer
10812                .push_excerpts(
10813                    buffer.clone(),
10814                    [
10815                        ExcerptRange {
10816                            context: Point::new(0, 0)..Point::new(1, 4),
10817                            primary: None,
10818                        },
10819                        ExcerptRange {
10820                            context: Point::new(1, 0)..Point::new(2, 4),
10821                            primary: None,
10822                        },
10823                    ],
10824                    cx,
10825                )
10826                .into_iter()
10827                .next();
10828            multibuffer
10829        });
10830        assert_eq!(
10831            multibuffer.read(cx).read(cx).text(),
10832            "aaaa\nbbbb\nbbbb\ncccc"
10833        );
10834        let (_, editor) = cx.add_window(Default::default(), |cx| {
10835            let mut editor = build_editor(multibuffer.clone(), cx);
10836            let snapshot = editor.snapshot(cx);
10837            editor.change_selections(None, cx, |s| {
10838                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
10839            });
10840            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
10841            assert_eq!(
10842                editor.selections.ranges(cx),
10843                [
10844                    Point::new(1, 3)..Point::new(1, 3),
10845                    Point::new(2, 1)..Point::new(2, 1),
10846                ]
10847            );
10848            editor
10849        });
10850
10851        // Refreshing selections is a no-op when excerpts haven't changed.
10852        editor.update(cx, |editor, cx| {
10853            editor.change_selections(None, cx, |s| {
10854                s.refresh();
10855            });
10856            assert_eq!(
10857                editor.selections.ranges(cx),
10858                [
10859                    Point::new(1, 3)..Point::new(1, 3),
10860                    Point::new(2, 1)..Point::new(2, 1),
10861                ]
10862            );
10863        });
10864
10865        multibuffer.update(cx, |multibuffer, cx| {
10866            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10867        });
10868        editor.update(cx, |editor, cx| {
10869            // Removing an excerpt causes the first selection to become degenerate.
10870            assert_eq!(
10871                editor.selections.ranges(cx),
10872                [
10873                    Point::new(0, 0)..Point::new(0, 0),
10874                    Point::new(0, 1)..Point::new(0, 1)
10875                ]
10876            );
10877
10878            // Refreshing selections will relocate the first selection to the original buffer
10879            // location.
10880            editor.change_selections(None, cx, |s| {
10881                s.refresh();
10882            });
10883            assert_eq!(
10884                editor.selections.ranges(cx),
10885                [
10886                    Point::new(0, 1)..Point::new(0, 1),
10887                    Point::new(0, 3)..Point::new(0, 3)
10888                ]
10889            );
10890            assert!(editor.selections.pending_anchor().is_some());
10891        });
10892    }
10893
10894    #[gpui::test]
10895    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10896        cx.set_global(Settings::test(cx));
10897        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10898        let mut excerpt1_id = None;
10899        let multibuffer = cx.add_model(|cx| {
10900            let mut multibuffer = MultiBuffer::new(0);
10901            excerpt1_id = multibuffer
10902                .push_excerpts(
10903                    buffer.clone(),
10904                    [
10905                        ExcerptRange {
10906                            context: Point::new(0, 0)..Point::new(1, 4),
10907                            primary: None,
10908                        },
10909                        ExcerptRange {
10910                            context: Point::new(1, 0)..Point::new(2, 4),
10911                            primary: None,
10912                        },
10913                    ],
10914                    cx,
10915                )
10916                .into_iter()
10917                .next();
10918            multibuffer
10919        });
10920        assert_eq!(
10921            multibuffer.read(cx).read(cx).text(),
10922            "aaaa\nbbbb\nbbbb\ncccc"
10923        );
10924        let (_, editor) = cx.add_window(Default::default(), |cx| {
10925            let mut editor = build_editor(multibuffer.clone(), cx);
10926            let snapshot = editor.snapshot(cx);
10927            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10928            assert_eq!(
10929                editor.selections.ranges(cx),
10930                [Point::new(1, 3)..Point::new(1, 3)]
10931            );
10932            editor
10933        });
10934
10935        multibuffer.update(cx, |multibuffer, cx| {
10936            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10937        });
10938        editor.update(cx, |editor, cx| {
10939            assert_eq!(
10940                editor.selections.ranges(cx),
10941                [Point::new(0, 0)..Point::new(0, 0)]
10942            );
10943
10944            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10945            editor.change_selections(None, cx, |s| {
10946                s.refresh();
10947            });
10948            assert_eq!(
10949                editor.selections.ranges(cx),
10950                [Point::new(0, 3)..Point::new(0, 3)]
10951            );
10952            assert!(editor.selections.pending_anchor().is_some());
10953        });
10954    }
10955
10956    #[gpui::test]
10957    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10958        cx.update(|cx| cx.set_global(Settings::test(cx)));
10959        let language = Arc::new(
10960            Language::new(
10961                LanguageConfig {
10962                    brackets: vec![
10963                        BracketPair {
10964                            start: "{".to_string(),
10965                            end: "}".to_string(),
10966                            close: true,
10967                            newline: true,
10968                        },
10969                        BracketPair {
10970                            start: "/* ".to_string(),
10971                            end: " */".to_string(),
10972                            close: true,
10973                            newline: true,
10974                        },
10975                    ],
10976                    ..Default::default()
10977                },
10978                Some(tree_sitter_rust::language()),
10979            )
10980            .with_indents_query("")
10981            .unwrap(),
10982        );
10983
10984        let text = concat!(
10985            "{   }\n",     // Suppress rustfmt
10986            "  x\n",       //
10987            "  /*   */\n", //
10988            "x\n",         //
10989            "{{} }\n",     //
10990        );
10991
10992        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10993        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10994        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10995        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10996            .await;
10997
10998        view.update(cx, |view, cx| {
10999            view.change_selections(None, cx, |s| {
11000                s.select_display_ranges([
11001                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
11002                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
11003                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
11004                ])
11005            });
11006            view.newline(&Newline, cx);
11007
11008            assert_eq!(
11009                view.buffer().read(cx).read(cx).text(),
11010                concat!(
11011                    "{ \n",    // Suppress rustfmt
11012                    "\n",      //
11013                    "}\n",     //
11014                    "  x\n",   //
11015                    "  /* \n", //
11016                    "  \n",    //
11017                    "  */\n",  //
11018                    "x\n",     //
11019                    "{{} \n",  //
11020                    "}\n",     //
11021                )
11022            );
11023        });
11024    }
11025
11026    #[gpui::test]
11027    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
11028        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
11029
11030        cx.set_global(Settings::test(cx));
11031        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
11032
11033        editor.update(cx, |editor, cx| {
11034            struct Type1;
11035            struct Type2;
11036
11037            let buffer = buffer.read(cx).snapshot(cx);
11038
11039            let anchor_range = |range: Range<Point>| {
11040                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
11041            };
11042
11043            editor.highlight_background::<Type1>(
11044                vec![
11045                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
11046                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
11047                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
11048                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
11049                ],
11050                |_| Color::red(),
11051                cx,
11052            );
11053            editor.highlight_background::<Type2>(
11054                vec![
11055                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
11056                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
11057                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
11058                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
11059                ],
11060                |_| Color::green(),
11061                cx,
11062            );
11063
11064            let snapshot = editor.snapshot(cx);
11065            let mut highlighted_ranges = editor.background_highlights_in_range(
11066                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
11067                &snapshot,
11068                cx.global::<Settings>().theme.as_ref(),
11069            );
11070            // Enforce a consistent ordering based on color without relying on the ordering of the
11071            // highlight's `TypeId` which is non-deterministic.
11072            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
11073            assert_eq!(
11074                highlighted_ranges,
11075                &[
11076                    (
11077                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
11078                        Color::green(),
11079                    ),
11080                    (
11081                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
11082                        Color::green(),
11083                    ),
11084                    (
11085                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
11086                        Color::red(),
11087                    ),
11088                    (
11089                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
11090                        Color::red(),
11091                    ),
11092                ]
11093            );
11094            assert_eq!(
11095                editor.background_highlights_in_range(
11096                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
11097                    &snapshot,
11098                    cx.global::<Settings>().theme.as_ref(),
11099                ),
11100                &[(
11101                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
11102                    Color::red(),
11103                )]
11104            );
11105        });
11106    }
11107
11108    #[gpui::test]
11109    fn test_following(cx: &mut gpui::MutableAppContext) {
11110        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
11111
11112        cx.set_global(Settings::test(cx));
11113
11114        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
11115        let (_, follower) = cx.add_window(
11116            WindowOptions {
11117                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
11118                ..Default::default()
11119            },
11120            |cx| build_editor(buffer.clone(), cx),
11121        );
11122
11123        let pending_update = Rc::new(RefCell::new(None));
11124        follower.update(cx, {
11125            let update = pending_update.clone();
11126            |_, cx| {
11127                cx.subscribe(&leader, move |_, leader, event, cx| {
11128                    leader
11129                        .read(cx)
11130                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
11131                })
11132                .detach();
11133            }
11134        });
11135
11136        // Update the selections only
11137        leader.update(cx, |leader, cx| {
11138            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
11139        });
11140        follower.update(cx, |follower, cx| {
11141            follower
11142                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11143                .unwrap();
11144        });
11145        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
11146
11147        // Update the scroll position only
11148        leader.update(cx, |leader, cx| {
11149            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
11150        });
11151        follower.update(cx, |follower, cx| {
11152            follower
11153                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11154                .unwrap();
11155        });
11156        assert_eq!(
11157            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
11158            vec2f(1.5, 3.5)
11159        );
11160
11161        // Update the selections and scroll position
11162        leader.update(cx, |leader, cx| {
11163            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
11164            leader.request_autoscroll(Autoscroll::Newest, cx);
11165            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
11166        });
11167        follower.update(cx, |follower, cx| {
11168            let initial_scroll_position = follower.scroll_position(cx);
11169            follower
11170                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11171                .unwrap();
11172            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
11173            assert!(follower.autoscroll_request.is_some());
11174        });
11175        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
11176
11177        // Creating a pending selection that precedes another selection
11178        leader.update(cx, |leader, cx| {
11179            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
11180            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
11181        });
11182        follower.update(cx, |follower, cx| {
11183            follower
11184                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11185                .unwrap();
11186        });
11187        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
11188
11189        // Extend the pending selection so that it surrounds another selection
11190        leader.update(cx, |leader, cx| {
11191            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
11192        });
11193        follower.update(cx, |follower, cx| {
11194            follower
11195                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11196                .unwrap();
11197        });
11198        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
11199    }
11200
11201    #[test]
11202    fn test_combine_syntax_and_fuzzy_match_highlights() {
11203        let string = "abcdefghijklmnop";
11204        let syntax_ranges = [
11205            (
11206                0..3,
11207                HighlightStyle {
11208                    color: Some(Color::red()),
11209                    ..Default::default()
11210                },
11211            ),
11212            (
11213                4..8,
11214                HighlightStyle {
11215                    color: Some(Color::green()),
11216                    ..Default::default()
11217                },
11218            ),
11219        ];
11220        let match_indices = [4, 6, 7, 8];
11221        assert_eq!(
11222            combine_syntax_and_fuzzy_match_highlights(
11223                string,
11224                Default::default(),
11225                syntax_ranges.into_iter(),
11226                &match_indices,
11227            ),
11228            &[
11229                (
11230                    0..3,
11231                    HighlightStyle {
11232                        color: Some(Color::red()),
11233                        ..Default::default()
11234                    },
11235                ),
11236                (
11237                    4..5,
11238                    HighlightStyle {
11239                        color: Some(Color::green()),
11240                        weight: Some(fonts::Weight::BOLD),
11241                        ..Default::default()
11242                    },
11243                ),
11244                (
11245                    5..6,
11246                    HighlightStyle {
11247                        color: Some(Color::green()),
11248                        ..Default::default()
11249                    },
11250                ),
11251                (
11252                    6..8,
11253                    HighlightStyle {
11254                        color: Some(Color::green()),
11255                        weight: Some(fonts::Weight::BOLD),
11256                        ..Default::default()
11257                    },
11258                ),
11259                (
11260                    8..9,
11261                    HighlightStyle {
11262                        weight: Some(fonts::Weight::BOLD),
11263                        ..Default::default()
11264                    },
11265                ),
11266            ]
11267        );
11268    }
11269
11270    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
11271        let point = DisplayPoint::new(row as u32, column as u32);
11272        point..point
11273    }
11274
11275    fn assert_selection_ranges(marked_text: &str, view: &mut Editor, cx: &mut ViewContext<Editor>) {
11276        let (text, ranges) = marked_text_ranges(marked_text, true);
11277        assert_eq!(view.text(cx), text);
11278        assert_eq!(
11279            view.selections.ranges(cx),
11280            ranges,
11281            "Assert selections are {}",
11282            marked_text
11283        );
11284    }
11285}
11286
11287trait RangeExt<T> {
11288    fn sorted(&self) -> Range<T>;
11289    fn to_inclusive(&self) -> RangeInclusive<T>;
11290}
11291
11292impl<T: Ord + Clone> RangeExt<T> for Range<T> {
11293    fn sorted(&self) -> Self {
11294        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
11295    }
11296
11297    fn to_inclusive(&self) -> RangeInclusive<T> {
11298        self.start.clone()..=self.end.clone()
11299    }
11300}
11301
11302trait RangeToAnchorExt {
11303    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
11304}
11305
11306impl<T: ToOffset> RangeToAnchorExt for Range<T> {
11307    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
11308        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
11309    }
11310}