1use lattice_grammar::AppEffect;
21use lattice_grammar::CommandRegistry;
22use lattice_grammar::HScroll;
23use lattice_grammar::ModalState;
24use lattice_grammar::PaneDirection;
25use lattice_grammar::Register;
26use lattice_grammar::ScrollPos;
27use lattice_grammar::SearchDirection;
28use lattice_grammar::ViewportPos;
29use lattice_grammar::VisualKind;
30use lattice_grammar::args::Args;
31use lattice_grammar::builtins::Builtins;
32use lattice_grammar::effect::Effect;
33use lattice_grammar::registry::ActionSpec;
34use lattice_grammar::registry::OperatorId;
35use lattice_protocol::ids::CommandId;
36use std::sync::Arc;
37
38#[derive(Debug, Clone, Copy, Default)]
46pub struct ActionIds {
47 pub match_bracket: CommandId,
48 pub toggle_case_at_cursor: CommandId,
49 pub open_line_below: CommandId,
50 pub open_line_above: CommandId,
51 pub lsp_hover_request: CommandId,
52 pub search_next: CommandId,
53 pub search_previous: CommandId,
54 pub error_next: CommandId,
56 pub error_prev: CommandId,
58 pub error_first: CommandId,
60 pub error_last: CommandId,
62 pub error_next_file: CommandId,
64 pub error_prev_file: CommandId,
66 pub jump_history_back: CommandId,
67 pub pane_history_back: CommandId,
69 pub pane_history_forward: CommandId,
70 pub jump_history_forward: CommandId,
71 pub walk_mark_history_back: CommandId,
72 pub walk_mark_history_forward: CommandId,
73 pub tag_stack_pop: CommandId,
74 pub open_fold_at_cursor: CommandId,
75 pub close_fold_at_cursor: CommandId,
76 pub toggle_fold_at_cursor: CommandId,
77 pub open_all_folds: CommandId,
78 pub close_all_folds: CommandId,
79 pub cycle_fold_at_cursor: CommandId,
80 pub cycle_folds_global: CommandId,
81 pub goto_parent_fold: CommandId,
82 pub delete_fold_at_cursor: CommandId,
83 pub open_folds_recursively: CommandId,
84 pub close_folds_recursively: CommandId,
85 pub delete_folds_recursively: CommandId,
86 pub goto_next_fold: CommandId,
87 pub goto_prev_fold: CommandId,
88 pub toggle_fold_enable: CommandId,
89 pub undo: CommandId,
90 pub redo: CommandId,
91 pub repeat_last_change: CommandId,
92 pub page_down: CommandId,
93 pub half_page_down: CommandId,
95 pub half_page_up: CommandId,
96 pub page_up: CommandId,
97 pub scroll_line_up: CommandId,
98 pub scroll_line_down: CommandId,
99 pub redraw_screen: CommandId,
100 pub open_command_picker: CommandId,
101 pub open_history_picker: CommandId,
103 pub open_search_history_picker: CommandId,
105 pub enter_command_line: CommandId,
106 pub command_line_submit: CommandId,
110 pub command_line_cancel: CommandId,
111 pub command_line_history_prev: CommandId,
112 pub command_line_history_next: CommandId,
113 pub command_line_complete: CommandId,
114 pub command_line_complete_prev: CommandId,
115 pub command_line_describe_under_cursor: CommandId,
116 pub command_line_toggle_expand: CommandId,
117 pub search_line_submit: CommandId,
119 pub search_line_cancel: CommandId,
121 pub search_line_backspace: CommandId,
126 pub search_line_history_prev: CommandId,
128 pub search_line_history_next: CommandId,
130 pub search_line_toggle_expand: CommandId,
132 pub prompt_line_submit: CommandId,
135 pub prompt_line_cancel: CommandId,
138 pub oil_navigate_up: CommandId,
139 pub reselect_last_visual: CommandId,
140 pub paste_after: CommandId,
141 pub paste_before: CommandId,
142 pub lsp_definition_request: CommandId,
143 pub lsp_declaration_request: CommandId,
144 pub lsp_type_definition_request: CommandId,
145 pub lsp_implementation_request: CommandId,
146 pub lsp_references_request: CommandId,
147 pub lsp_follow_link_at_cursor: CommandId,
148 pub enter_append: CommandId,
149 pub enter_insert_first_non_blank: CommandId,
150 pub enter_append_end_of_line: CommandId,
151 pub display_line_down: CommandId,
152 pub display_line_up: CommandId,
153 pub display_line_start: CommandId,
154 pub display_line_end: CommandId,
155 pub create_fold_from_visual: CommandId,
156 pub delete_char_backward: CommandId,
157 pub insert_cursor_line_start: CommandId,
160 pub insert_cursor_line_end: CommandId,
161 pub insert_cursor_char_left: CommandId,
162 pub insert_cursor_char_right: CommandId,
163 pub insert_delete_word_backward: CommandId,
164 pub insert_delete_to_line_start: CommandId,
165 pub insert_kill_to_line_end: CommandId,
166 pub insert_indent_line: CommandId,
167 pub insert_dedent_line: CommandId,
168 pub completion_trigger: CommandId,
169 pub snippet_expand: CommandId,
170 pub lsp_diagnostic_popup: CommandId,
175 pub exit_visual: CommandId,
176 pub swap_visual_ends: CommandId,
177 pub replace_undo_last: CommandId,
178 pub enter_mode_insert: CommandId,
179 pub enter_mode_normal: CommandId,
180 pub enter_mode_replace: CommandId,
181 pub enter_visual_charwise: CommandId,
182 pub enter_visual_linewise: CommandId,
183 pub enter_visual_blockwise: CommandId,
184 pub enter_select_charwise: CommandId,
186 pub enter_select_linewise: CommandId,
187 pub enter_select_blockwise: CommandId,
188 pub enter_search_forward: CommandId,
189 pub enter_search_backward: CommandId,
190 pub search_word_under_cursor_forward: CommandId,
191 pub search_word_under_cursor_backward: CommandId,
192 pub jump_viewport_top: CommandId,
193 pub jump_viewport_middle: CommandId,
194 pub jump_viewport_bottom: CommandId,
195 pub scroll_cursor_to_top: CommandId,
196 pub scroll_cursor_to_center: CommandId,
197 pub scroll_cursor_to_bottom: CommandId,
198 pub h_scroll_right: CommandId,
199 pub h_scroll_left: CommandId,
200 pub h_scroll_half_right: CommandId,
201 pub h_scroll_half_left: CommandId,
202 pub h_scroll_cursor_left_edge: CommandId,
203 pub h_scroll_cursor_right_edge: CommandId,
204 pub join_lines_with_space: CommandId,
205 pub join_lines_bare: CommandId,
206 pub find_repeat_forward: CommandId,
207 pub find_repeat_reverse: CommandId,
208 pub insert_newline: CommandId,
209 pub insert_tab: CommandId,
210 pub overwrite_char: CommandId,
211 pub set_mark: CommandId,
212 pub jump_to_mark_line: CommandId,
213 pub jump_to_mark_exact: CommandId,
214 pub select_register: CommandId,
215 pub start_macro_record: CommandId,
216 pub play_macro: CommandId,
217 pub absorb_operator_delete: CommandId,
226 pub absorb_operator_change: CommandId,
227 pub absorb_operator_yank: CommandId,
228 pub absorb_operator_indent_right: CommandId,
229 pub absorb_operator_indent_left: CommandId,
230 pub absorb_operator_reindent: CommandId,
232 pub absorb_operator_reflow: CommandId,
234 pub absorb_operator_upper: CommandId,
235 pub absorb_operator_lower: CommandId,
236 pub absorb_operator_toggle_case: CommandId,
237 pub absorb_operator_search: CommandId,
238 pub split_pane_horizontal: CommandId,
239 pub split_pane_vertical: CommandId,
240 pub close_pane: CommandId,
241 pub only_pane: CommandId,
244 pub toggle_zoom_pane: CommandId,
246 pub navigate_pane_left: CommandId,
247 pub navigate_pane_down: CommandId,
248 pub navigate_pane_up: CommandId,
249 pub navigate_pane_right: CommandId,
250 pub next_pane: CommandId,
251 pub prev_pane: CommandId,
252 pub equalize_panes: CommandId,
254 pub grow_pane_height: CommandId,
255 pub shrink_pane_height: CommandId,
256 pub grow_pane_width: CommandId,
257 pub shrink_pane_width: CommandId,
258 pub picker_accept_in_split: CommandId,
262 pub picker_accept_in_vsplit: CommandId,
263 pub picker_accept_in_tab: CommandId,
264 pub next_tab: CommandId,
266 pub prev_tab: CommandId,
267 pub new_tab: CommandId,
268 pub close_tab: CommandId,
269 pub only_tab: CommandId,
274 pub quit: CommandId,
279 pub cancel: CommandId,
283 pub move_tab: CommandId,
284 pub move_pane_to_new_tab: CommandId,
288 pub completion_next: CommandId,
294 pub completion_prev: CommandId,
295 pub completion_accept: CommandId,
296 pub completion_cancel: CommandId,
297 pub completion_cancel_and_exit_insert: CommandId,
298 pub completion_toggle_docs: CommandId,
299 pub completion_docs_scroll_down: CommandId,
300 pub completion_docs_scroll_up: CommandId,
301 pub completion_accept_then_insert: CommandId,
302 pub insert_register: CommandId,
304 pub open_yank_picker: CommandId,
306 pub open_arg_picker: CommandId,
308 pub completion_filter_to_source: CommandId,
313 pub completion_filter_clear: CommandId,
315 pub snippet_next_placeholder: CommandId,
322 pub snippet_prev_placeholder: CommandId,
323 pub snippet_leave: CommandId,
324 pub search_refresh: CommandId,
328 pub compilation_recompile: CommandId,
332 pub compilation_jump: CommandId,
339 pub multibuffer_jump_to_source: CommandId,
347}
348
349pub fn populate(registry: &mut CommandRegistry, builtins: &Builtins) -> ActionIds {
354 ActionIds {
358 match_bracket: register_simple(
359 registry,
360 "action:match-bracket",
361 "Vim's `%`: jump to the matching bracket.",
362 AppEffect::MatchBracket,
363 ),
364 toggle_case_at_cursor: register_simple(
365 registry,
366 "action:toggle-case-at-cursor",
367 "Vim's `~`: toggle the case of the char at the cursor.",
368 AppEffect::ToggleCaseAtCursor,
369 ),
370 open_line_below: register_simple(
371 registry,
372 "action:open-line-below",
373 "Vim's `o`: open a new line below and enter Insert.",
374 AppEffect::OpenLineBelow,
375 ),
376 open_line_above: register_simple(
377 registry,
378 "action:open-line-above",
379 "Vim's `O`: open a new line above and enter Insert.",
380 AppEffect::OpenLineAbove,
381 ),
382 lsp_hover_request: registry.register_action(
389 "action:lsp-hover",
390 "`K`: send `textDocument/hover` to attached LSP servers \
391 (mode-owned; `lsp-mode`'s handler emits `Effect::Lsp(LspRequest::Hover)`).",
392 ActionSpec {
393 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
394 args_schema: vec![],
395 },
396 ),
397 search_next: register_simple(
398 registry,
399 "action:search-next",
400 "Vim's `n`: re-run the last search forward.",
401 AppEffect::SearchNext,
402 ),
403 search_previous: register_simple(
404 registry,
405 "action:search-previous",
406 "Vim's `N`: re-run the last search in the reverse direction.",
407 AppEffect::SearchPrevious,
408 ),
409 error_next: register_simple(
410 registry,
411 "action:error-next",
412 "`]qq`: jump to the next error entry (wraps; echoes `no error list` when empty).",
413 AppEffect::ErrorNav {
414 target: lattice_grammar::ErrorTarget::Next,
415 },
416 ),
417 error_prev: register_simple(
418 registry,
419 "action:error-prev",
420 "`[qq`: jump to the previous error entry (wraps; echoes `no error list` when empty).",
421 AppEffect::ErrorNav {
422 target: lattice_grammar::ErrorTarget::Prev,
423 },
424 ),
425 error_first: register_simple(
426 registry,
427 "action:error-first",
428 "`[Q`: jump to the first error entry (`:cfirst`).",
429 AppEffect::ErrorNav {
430 target: lattice_grammar::ErrorTarget::First,
431 },
432 ),
433 error_last: register_simple(
434 registry,
435 "action:error-last",
436 "`]Q`: jump to the last error entry (`:clast`).",
437 AppEffect::ErrorNav {
438 target: lattice_grammar::ErrorTarget::Last,
439 },
440 ),
441 error_next_file: register_simple(
442 registry,
443 "action:error-next-file",
444 "`]qf`: jump to the first entry of the next file (`:cnextfile`; wraps).",
445 AppEffect::ErrorNav {
446 target: lattice_grammar::ErrorTarget::NextFile,
447 },
448 ),
449 error_prev_file: register_simple(
450 registry,
451 "action:error-prev-file",
452 "`[qf`: jump to the first entry of the previous file (`:cprevfile`; wraps).",
453 AppEffect::ErrorNav {
454 target: lattice_grammar::ErrorTarget::PrevFile,
455 },
456 ),
457 pane_history_back: register_simple(
458 registry,
459 "action:pane-history-back",
460 "`<C-6>`: step back through the active pane's buffer history.",
461 AppEffect::PaneHistoryBack,
462 ),
463 pane_history_forward: register_simple(
464 registry,
465 "action:pane-history-forward",
466 "`<C-7>`: step forward through the active pane's buffer history.",
467 AppEffect::PaneHistoryForward,
468 ),
469 jump_history_back: register_simple(
470 registry,
471 "action:jump-history-back",
472 "Vim's `<C-o>`: step backward through the position history.",
473 AppEffect::JumpHistoryBack,
474 ),
475 jump_history_forward: register_simple(
476 registry,
477 "action:jump-history-forward",
478 "Vim's `<C-i>`: step forward through the position history.",
479 AppEffect::JumpHistoryForward,
480 ),
481 walk_mark_history_back: register_simple(
482 registry,
483 "action:walk-mark-history-back",
484 "Vim's `g;`: walk backward through the mark history.",
485 AppEffect::WalkMarkHistoryBack,
486 ),
487 walk_mark_history_forward: register_simple(
488 registry,
489 "action:walk-mark-history-forward",
490 "Vim's `g,`: walk forward through the mark history.",
491 AppEffect::WalkMarkHistoryForward,
492 ),
493 tag_stack_pop: register_simple(
494 registry,
495 "action:tag-stack-pop",
496 "Vim's `<C-t>`: pop the tag stack and jump back to the prior origin.",
497 AppEffect::TagStackPop,
498 ),
499 open_fold_at_cursor: register_simple(
500 registry,
501 "action:open-fold-at-cursor",
502 "Vim's `zo`: open the fold containing the cursor.",
503 AppEffect::OpenFoldAtCursor,
504 ),
505 close_fold_at_cursor: register_simple(
506 registry,
507 "action:close-fold-at-cursor",
508 "Vim's `zc`: close the fold containing the cursor.",
509 AppEffect::CloseFoldAtCursor,
510 ),
511 toggle_fold_at_cursor: register_simple(
512 registry,
513 "action:toggle-fold-at-cursor",
514 "Vim's `za`: toggle the fold containing the cursor.",
515 AppEffect::ToggleFoldAtCursor,
516 ),
517 open_all_folds: register_simple(
518 registry,
519 "action:open-all-folds",
520 "Vim's `zR`: open every fold in the buffer.",
521 AppEffect::OpenAllFolds,
522 ),
523 close_all_folds: register_simple(
524 registry,
525 "action:close-all-folds",
526 "Vim's `zM`: close every fold in the buffer.",
527 AppEffect::CloseAllFolds,
528 ),
529 cycle_fold_at_cursor: register_simple(
530 registry,
531 "action:fold-cycle",
532 "org-cycle (`z<Space>`): cycle the fold under the cursor through \
533 FOLDED → CHILDREN → SUBTREE.",
534 AppEffect::CycleFoldAtCursor,
535 ),
536 cycle_folds_global: register_simple(
537 registry,
538 "action:fold-cycle-global",
539 "org-cycle (`z<Tab>`): cycle the whole buffer through \
540 OVERVIEW → CONTENTS → SHOW-ALL.",
541 AppEffect::CycleFoldsGlobal,
542 ),
543 goto_parent_fold: register_simple(
544 registry,
545 "action:fold-goto-parent",
546 "Move the cursor to the parent heading, one level up the fold \
547 hierarchy (`zp`).",
548 AppEffect::GotoParentFold,
549 ),
550 delete_fold_at_cursor: register_simple(
551 registry,
552 "action:delete-fold-at-cursor",
553 "Vim's `zd`: delete the fold containing the cursor.",
554 AppEffect::DeleteFoldAtCursor,
555 ),
556 open_folds_recursively: register_simple(
557 registry,
558 "action:open-folds-recursively",
559 "Vim's `zO`: open every fold containing the cursor and the folds \
560 nested inside them. In Visual, over every selected line.",
561 AppEffect::OpenFoldsRecursively,
562 ),
563 close_folds_recursively: register_simple(
564 registry,
565 "action:close-folds-recursively",
566 "Vim's `zC`: close every fold containing the cursor. In Visual, \
567 every fold containing a selected line.",
568 AppEffect::CloseFoldsRecursively,
569 ),
570 delete_folds_recursively: register_simple(
571 registry,
572 "action:delete-folds-recursively",
573 "Vim's `zD`: delete the innermost fold containing the cursor and the \
574 folds nested inside it. In Visual, the folds inside the selection.",
575 AppEffect::DeleteFoldsRecursively,
576 ),
577 goto_next_fold: register_simple(
578 registry,
579 "action:goto-next-fold",
580 "Vim's `zj`: move cursor to the start of the next fold.",
581 AppEffect::GotoNextFold,
582 ),
583 goto_prev_fold: register_simple(
584 registry,
585 "action:goto-prev-fold",
586 "Vim's `zk`: move cursor to the end of the previous fold.",
587 AppEffect::GotoPrevFold,
588 ),
589 toggle_fold_enable: register_simple(
590 registry,
591 "action:toggle-fold-enable",
592 "Vim's `zi`: toggle the `foldenable` option.",
593 AppEffect::ToggleFoldEnable,
594 ),
595 undo: register_simple(
596 registry,
597 "action:undo",
598 "Vim's `u`: undo the last buffer change.",
599 AppEffect::Undo,
600 ),
601 redo: register_simple(
602 registry,
603 "action:redo",
604 "Vim's `<C-r>`: redo the last undone change.",
605 AppEffect::Redo,
606 ),
607 repeat_last_change: register_simple(
608 registry,
609 "action:repeat-last-change",
610 "Vim's `.`: repeat the last change.",
611 AppEffect::RepeatLastChange,
612 ),
613 page_down: register_simple(
614 registry,
615 "action:page-down",
616 "Vim's `<C-f>`: scroll the viewport down one page.",
617 AppEffect::PageDown,
618 ),
619 half_page_down: register_simple(
620 registry,
621 "action:half-page-down",
622 "Vim's `<C-d>`: scroll the view and the cursor down by `scroll` lines.",
623 AppEffect::HalfPageDown,
624 ),
625 half_page_up: register_simple(
626 registry,
627 "action:half-page-up",
628 "Vim's `<C-u>`: scroll the view and the cursor up by `scroll` lines.",
629 AppEffect::HalfPageUp,
630 ),
631 page_up: register_simple(
632 registry,
633 "action:page-up",
634 "Vim's `<C-b>`: scroll the viewport up one page.",
635 AppEffect::PageUp,
636 ),
637 scroll_line_up: register_simple(
638 registry,
639 "action:scroll-line-up",
640 "Vim's `<C-y>`: scroll viewport up one line.",
641 AppEffect::ScrollLineUp,
642 ),
643 scroll_line_down: register_simple(
644 registry,
645 "action:scroll-line-down",
646 "Vim's `<C-e>`: scroll viewport down one line.",
647 AppEffect::ScrollLineDown,
648 ),
649 redraw_screen: register_simple(
650 registry,
651 "action:redraw-screen",
652 "Vim's `<C-l>`: force a full screen redraw.",
653 AppEffect::RedrawScreen,
654 ),
655 open_command_picker: register_simple(
656 registry,
657 "action:open-command-picker",
658 "Vim's `:` / Emacs' `M-x`: open the command picker.",
659 AppEffect::OpenCommandPicker,
660 ),
661 open_history_picker: register_simple(
662 registry,
663 "action:open-history-picker",
664 "Vim's `q:`: open the command-line history picker (accept loads into the `:` line, does not execute).",
665 AppEffect::OpenHistoryPicker,
666 ),
667 open_search_history_picker: register_simple(
668 registry,
669 "action:open-search-history-picker",
670 "Vim's `q/` / `q?`: open the search-line history picker (accept loads into the `/` line, does not execute).",
671 AppEffect::OpenSearchHistoryPicker,
672 ),
673 enter_command_line: register_simple(
674 registry,
675 "action:enter-command-line",
676 "Vim's `:`: enter the command-line minibuffer.",
677 AppEffect::EnterCommandLine,
678 ),
679 command_line_submit: register_simple(
680 registry,
681 "action:command-line-submit",
682 "MB.1: submit the `:` command line (or accept the open completion candidate).",
683 AppEffect::CommandLineSubmit,
684 ),
685 command_line_cancel: register_simple(
686 registry,
687 "action:command-line-cancel",
688 "MB.1: cancel the `:` command line (or dismiss the completion popup first).",
689 AppEffect::CommandLineCancel,
690 ),
691 command_line_history_prev: register_simple(
692 registry,
693 "action:command-line-history-prev",
694 "MB.1: previous `:` history entry (or previous completion candidate).",
695 AppEffect::CommandLineHistoryPrev,
696 ),
697 command_line_history_next: register_simple(
698 registry,
699 "action:command-line-history-next",
700 "MB.1: next `:` history entry (or next completion candidate).",
701 AppEffect::CommandLineHistoryNext,
702 ),
703 command_line_complete: register_simple(
704 registry,
705 "action:command-line-complete",
706 "MB.1: open the `:` completion popup or advance the selection.",
707 AppEffect::CommandLineComplete,
708 ),
709 command_line_complete_prev: register_simple(
710 registry,
711 "action:command-line-complete-prev",
712 "MB.1: previous `:` completion candidate.",
713 AppEffect::CommandLineCompletePrev,
714 ),
715 command_line_describe_under_cursor: register_simple(
716 registry,
717 "action:command-line-describe-under-cursor",
718 "MB.1: describe the command / arg under the `:` cursor.",
719 AppEffect::CommandLineDescribeUnderCursor,
720 ),
721 command_line_toggle_expand: register_simple(
722 registry,
723 "action:command-line-toggle-expand",
724 "MB.2: `<C-x><C-e>`: expand the `:` line into the full-modal \
725 mini-buffer band, or collapse it back to the one-row line.",
726 AppEffect::CommandLineToggleExpand,
727 ),
728 search_line_submit: register_simple(
729 registry,
730 "action:search-line-submit",
731 "MB.5a: `<CR>` on the `/`·`?` search line — submit the search \
732 pattern.",
733 AppEffect::SearchLineSubmit,
734 ),
735 search_line_cancel: register_simple(
736 registry,
737 "action:search-line-cancel",
738 "MB.5a: `<Esc>` / `<C-c>` on the `/`·`?` search line — cancel \
739 the search and restore the prior editing buffer.",
740 AppEffect::SearchLineCancel,
741 ),
742 search_line_backspace: register_simple(
743 registry,
744 "action:search-line-backspace",
745 "`<BS>` on the `/`·`?` search line — delete the character \
746 before the cursor, or cancel the search when the pattern \
747 is already empty (vim's behaviour).",
748 AppEffect::SearchLineBackspace,
749 ),
750 search_line_history_prev: register_simple(
751 registry,
752 "action:search-line-history-prev",
753 "MB.5b: `<C-p>` / `<Up>` on the `/`·`?` search line — previous \
754 search history entry.",
755 AppEffect::SearchLineHistoryPrev,
756 ),
757 search_line_history_next: register_simple(
758 registry,
759 "action:search-line-history-next",
760 "MB.5b: `<C-n>` / `<Down>` on the `/`·`?` search line — next \
761 search history entry.",
762 AppEffect::SearchLineHistoryNext,
763 ),
764 search_line_toggle_expand: register_simple(
765 registry,
766 "action:search-line-toggle-expand",
767 "MB.5c: `<C-x><C-e>` on the `/`·`?` search line — toggle the \
768 expanded tier-2 mini-buffer band.",
769 AppEffect::SearchLineToggleExpand,
770 ),
771 prompt_line_submit: register_simple(
772 registry,
773 "action:prompt-line-submit",
774 "Submit a generic `Effect::OpenPrompt` prompt.",
775 AppEffect::PromptLineSubmit,
776 ),
777 prompt_line_cancel: register_simple(
778 registry,
779 "action:prompt-line-cancel",
780 "Cancel a generic `Effect::OpenPrompt` prompt.",
781 AppEffect::PromptLineCancel,
782 ),
783 oil_navigate_up: register_simple(
784 registry,
785 "action:oil-navigate-up",
786 "Lattice's `-`: open / step up in the oil-style directory view.",
787 AppEffect::OilNavigateUp,
788 ),
789 reselect_last_visual: register_simple(
790 registry,
791 "action:reselect-last-visual",
792 "Vim's `gv`: reselect the last Visual selection.",
793 AppEffect::ReselectLastVisual,
794 ),
795 paste_after: register_simple(
796 registry,
797 "action:paste-after",
798 "Vim's `p`: paste the unnamed register's contents after the cursor.",
799 AppEffect::PasteAfter,
800 ),
801 paste_before: register_simple(
802 registry,
803 "action:paste-before",
804 "Vim's `P`: paste the unnamed register's contents before the cursor.",
805 AppEffect::PasteBefore,
806 ),
807 lsp_definition_request: registry.register_action(
813 "action:lsp-definition",
814 "`gd`: send `textDocument/definition` to attached LSP servers \
815 (mode-owned; emits `Effect::Lsp(LspRequest::Definition)`).",
816 ActionSpec {
817 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
818 args_schema: vec![],
819 },
820 ),
821 lsp_declaration_request: registry.register_action(
822 "action:lsp-declaration",
823 "`gD`: send `textDocument/declaration` to attached LSP servers \
824 (mode-owned; emits `Effect::Lsp(LspRequest::Declaration)`).",
825 ActionSpec {
826 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
827 args_schema: vec![],
828 },
829 ),
830 lsp_type_definition_request: registry.register_action(
831 "action:lsp-type-definition",
832 "`gy`: send `textDocument/typeDefinition` to attached LSP servers \
833 (mode-owned; emits `Effect::Lsp(LspRequest::TypeDefinition)`).",
834 ActionSpec {
835 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
836 args_schema: vec![],
837 },
838 ),
839 lsp_implementation_request: registry.register_action(
840 "action:lsp-implementation",
841 "`gI`: send `textDocument/implementation` to attached LSP servers \
842 (mode-owned; emits `Effect::Lsp(LspRequest::Implementation)`).",
843 ActionSpec {
844 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
845 args_schema: vec![],
846 },
847 ),
848 lsp_references_request: registry.register_action(
849 "action:lsp-references",
850 "`gr`: send `textDocument/references` to attached LSP servers \
851 (mode-owned; emits `Effect::Lsp(LspRequest::References)`).",
852 ActionSpec {
853 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
854 args_schema: vec![],
855 },
856 ),
857 lsp_follow_link_at_cursor: registry.register_action(
858 "action:lsp-follow-link",
859 "`gx`: follow the `textDocument/documentLink` covering the cursor \
860 (mode-owned; emits `Effect::Lsp(LspRequest::FollowLink)`).",
861 ActionSpec {
862 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
863 args_schema: vec![],
864 },
865 ),
866 enter_append: register_simple(
867 registry,
868 "action:enter-append",
869 "Vim's `a`: move right one byte and enter Insert.",
870 AppEffect::EnterAppend,
871 ),
872 insert_cursor_line_start: register_simple(
873 registry,
874 "action:insert-cursor-line-start",
875 "Insert `<C-a>`: move the caret to the start of the line (readline).",
876 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::CursorLineStart),
877 ),
878 insert_cursor_line_end: register_simple(
879 registry,
880 "action:insert-cursor-line-end",
881 "Insert `<C-e>`: move the caret to the end of the line (readline).",
882 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::CursorLineEnd),
883 ),
884 insert_cursor_char_left: register_simple(
885 registry,
886 "action:insert-cursor-char-left",
887 "Insert `<C-b>`: move the caret one character left (readline).",
888 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::CursorCharLeft),
889 ),
890 insert_cursor_char_right: register_simple(
891 registry,
892 "action:insert-cursor-char-right",
893 "Insert `<C-f>`: move the caret one character right (readline).",
894 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::CursorCharRight),
895 ),
896 insert_delete_word_backward: register_simple(
897 registry,
898 "action:insert-delete-word-backward",
899 "Insert `<C-w>`: delete the word before the caret (readline/vim).",
900 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::DeleteWordBackward),
901 ),
902 insert_delete_to_line_start: register_simple(
903 registry,
904 "action:insert-delete-to-line-start",
905 "Insert `<C-u>`: delete from the line start to the caret (readline/vim).",
906 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::DeleteToLineStart),
907 ),
908 insert_kill_to_line_end: register_simple(
909 registry,
910 "action:insert-kill-to-line-end",
911 "Insert `<C-k>`: delete from the caret to the line end (readline).",
912 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::KillToLineEnd),
913 ),
914 insert_indent_line: register_simple(
915 registry,
916 "action:insert-indent-line",
917 "Insert `<C-t>`: indent the current line by one shiftwidth (vim).",
918 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::IndentLine),
919 ),
920 insert_dedent_line: register_simple(
921 registry,
922 "action:insert-dedent-line",
923 "Insert `<C-d>`: dedent the current line by one shiftwidth (vim).",
924 AppEffect::InsertLineEdit(lattice_grammar::InsertLineEdit::DedentLine),
925 ),
926 enter_insert_first_non_blank: register_simple(
927 registry,
928 "action:enter-insert-first-non-blank",
929 "Vim's `I`: move to first non-blank of line and enter Insert.",
930 AppEffect::EnterInsertFirstNonBlank,
931 ),
932 enter_append_end_of_line: register_simple(
933 registry,
934 "action:enter-append-end-of-line",
935 "Vim's `A`: move to end of line and enter Insert.",
936 AppEffect::EnterAppendEndOfLine,
937 ),
938 display_line_down: register_simple(
939 registry,
940 "action:display-line-down",
941 "Vim's `gj`: move down one display line (wrap segment).",
942 AppEffect::DisplayLineDown,
943 ),
944 display_line_up: register_simple(
945 registry,
946 "action:display-line-up",
947 "Vim's `gk`: move up one display line (wrap segment).",
948 AppEffect::DisplayLineUp,
949 ),
950 display_line_start: register_simple(
951 registry,
952 "action:display-line-start",
953 "Vim's `g0`: move to the start of the current display segment.",
954 AppEffect::DisplayLineStart,
955 ),
956 display_line_end: register_simple(
957 registry,
958 "action:display-line-end",
959 "Vim's `g$`: move to the end of the current display segment.",
960 AppEffect::DisplayLineEnd,
961 ),
962 create_fold_from_visual: register_simple(
963 registry,
964 "action:create-fold-from-visual",
965 "Vim's `zf`: create a fold from the most recent Visual selection.",
966 AppEffect::CreateFoldFromVisual,
967 ),
968 delete_char_backward: register_simple(
969 registry,
970 "action:delete-char-backward",
971 "Insert mode's `<BS>`: delete the byte before the cursor.",
972 AppEffect::DeleteCharBackward,
973 ),
974 completion_trigger: register_simple(
975 registry,
976 "action:completion-trigger",
977 "Insert mode's `<C-Space>` / `<C-x><C-o>`: trigger the completion popup.",
978 AppEffect::CompletionTrigger,
979 ),
980 snippet_expand: registry.register_action(
988 "action:snippet-expand",
989 "Insert mode's `<C-x><C-s>`: direct snippet expansion (mode-owned; \
990 `snippet-mode`'s handler emits `Effect::ExpandSnippet`).",
991 ActionSpec {
992 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
993 args_schema: vec![],
994 },
995 ),
996 lsp_diagnostic_popup: registry.register_action(
1002 "action:lsp-diagnostic-popup",
1003 "lsp-diagnostics-mode's `gl`: show the cursor line's diagnostics in a \
1004 cursor-anchored popup (mode-owned; the handler emits \
1005 `Effect::ShowDiagnosticsPopup`).",
1006 ActionSpec {
1007 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
1008 args_schema: vec![],
1009 },
1010 ),
1011 exit_visual: register_simple(
1012 registry,
1013 "action:exit-visual",
1014 "Visual mode's `<Esc>` / `v` / `V`: exit Visual to Normal.",
1015 AppEffect::ExitVisual,
1016 ),
1017 swap_visual_ends: register_simple(
1018 registry,
1019 "action:swap-visual-ends",
1020 "Visual mode's `o`: swap the cursor to the other end of the selection.",
1021 AppEffect::SwapVisualEnds,
1022 ),
1023 replace_undo_last: register_simple(
1024 registry,
1025 "action:replace-undo-last",
1026 "Replace mode's `<BS>`: undo the last overwritten char.",
1027 AppEffect::ReplaceUndoLast,
1028 ),
1029 enter_mode_insert: register_simple(
1030 registry,
1031 "action:enter-mode-insert",
1032 "Vim's `i`: enter Insert mode at the cursor.",
1033 AppEffect::EnterMode(ModalState::Insert),
1034 ),
1035 enter_mode_normal: register_simple(
1036 registry,
1037 "action:enter-mode-normal",
1038 "Vim's `<Esc>` (from Insert / Replace): return to Normal mode.",
1039 AppEffect::EnterMode(ModalState::Normal),
1040 ),
1041 enter_mode_replace: register_simple(
1042 registry,
1043 "action:enter-mode-replace",
1044 "Vim's `R`: enter Replace mode.",
1045 AppEffect::EnterMode(ModalState::Replace),
1046 ),
1047 enter_visual_charwise: register_simple(
1048 registry,
1049 "action:enter-visual-charwise",
1050 "Vim's `v`: enter charwise Visual at the current cursor.",
1051 AppEffect::EnterVisual(VisualKind::Charwise),
1052 ),
1053 enter_visual_linewise: register_simple(
1054 registry,
1055 "action:enter-visual-linewise",
1056 "Vim's `V`: enter linewise Visual at the current cursor.",
1057 AppEffect::EnterVisual(VisualKind::Linewise),
1058 ),
1059 enter_visual_blockwise: register_simple(
1060 registry,
1061 "action:enter-visual-blockwise",
1062 "Vim's `<C-v>` / `<C-q>`: enter blockwise Visual at the current cursor.",
1063 AppEffect::EnterVisual(VisualKind::Blockwise),
1064 ),
1065 enter_select_charwise: register_simple(
1066 registry,
1067 "action:enter-select-charwise",
1068 "Vim's `gh`: enter charwise Select at the current cursor (SN.3d).",
1069 AppEffect::EnterSelect(VisualKind::Charwise),
1070 ),
1071 enter_select_linewise: register_simple(
1072 registry,
1073 "action:enter-select-linewise",
1074 "Vim's `gH`: enter linewise Select at the current cursor (SN.3d).",
1075 AppEffect::EnterSelect(VisualKind::Linewise),
1076 ),
1077 enter_select_blockwise: register_simple(
1078 registry,
1079 "action:enter-select-blockwise",
1080 "Vim's `g<C-h>`: enter blockwise Select at the current cursor (SN.3d).",
1081 AppEffect::EnterSelect(VisualKind::Blockwise),
1082 ),
1083 enter_search_forward: register_simple(
1084 registry,
1085 "action:enter-search-forward",
1086 "Vim's `/`: enter the Search minibuffer searching forward.",
1087 AppEffect::EnterSearch(SearchDirection::Forward),
1088 ),
1089 enter_search_backward: register_simple(
1090 registry,
1091 "action:enter-search-backward",
1092 "Vim's `?`: enter the Search minibuffer searching backward.",
1093 AppEffect::EnterSearch(SearchDirection::Backward),
1094 ),
1095 search_word_under_cursor_forward: register_simple(
1096 registry,
1097 "action:search-word-under-cursor-forward",
1098 "Vim's `*`: search forward for the word under the cursor.",
1099 AppEffect::SearchWordUnderCursor(SearchDirection::Forward),
1100 ),
1101 search_word_under_cursor_backward: register_simple(
1102 registry,
1103 "action:search-word-under-cursor-backward",
1104 "Vim's `#`: search backward for the word under the cursor.",
1105 AppEffect::SearchWordUnderCursor(SearchDirection::Backward),
1106 ),
1107 jump_viewport_top: register_simple(
1108 registry,
1109 "action:jump-viewport-top",
1110 "Vim's `H`: jump cursor to the top visible line.",
1111 AppEffect::JumpViewport(ViewportPos::Top),
1112 ),
1113 jump_viewport_middle: register_simple(
1114 registry,
1115 "action:jump-viewport-middle",
1116 "Vim's `M`: jump cursor to the middle visible line.",
1117 AppEffect::JumpViewport(ViewportPos::Middle),
1118 ),
1119 jump_viewport_bottom: register_simple(
1120 registry,
1121 "action:jump-viewport-bottom",
1122 "Vim's `L`: jump cursor to the bottom visible line.",
1123 AppEffect::JumpViewport(ViewportPos::Bottom),
1124 ),
1125 scroll_cursor_to_top: register_simple(
1126 registry,
1127 "action:scroll-cursor-to-top",
1128 "Vim's `zt`: scroll viewport so the cursor's line sits at the top.",
1129 AppEffect::ScrollCursorTo(ScrollPos::Top),
1130 ),
1131 scroll_cursor_to_center: register_simple(
1132 registry,
1133 "action:scroll-cursor-to-center",
1134 "Vim's `zz`: scroll viewport so the cursor's line sits at the centre.",
1135 AppEffect::ScrollCursorTo(ScrollPos::Center),
1136 ),
1137 scroll_cursor_to_bottom: register_simple(
1138 registry,
1139 "action:scroll-cursor-to-bottom",
1140 "Vim's `zb`: scroll viewport so the cursor's line sits at the bottom.",
1141 AppEffect::ScrollCursorTo(ScrollPos::Bottom),
1142 ),
1143 h_scroll_right: register_simple(
1144 registry,
1145 "action:h-scroll-right",
1146 "Vim's `zl`: scroll the view right by [count] columns (wrap off).",
1147 AppEffect::HorizontalScroll(HScroll::Columns { right: true }),
1148 ),
1149 h_scroll_left: register_simple(
1150 registry,
1151 "action:h-scroll-left",
1152 "Vim's `zh`: scroll the view left by [count] columns (wrap off).",
1153 AppEffect::HorizontalScroll(HScroll::Columns { right: false }),
1154 ),
1155 h_scroll_half_right: register_simple(
1156 registry,
1157 "action:h-scroll-half-right",
1158 "Vim's `zL`: scroll the view right by half the body width.",
1159 AppEffect::HorizontalScroll(HScroll::HalfScreen { right: true }),
1160 ),
1161 h_scroll_half_left: register_simple(
1162 registry,
1163 "action:h-scroll-half-left",
1164 "Vim's `zH`: scroll the view left by half the body width.",
1165 AppEffect::HorizontalScroll(HScroll::HalfScreen { right: false }),
1166 ),
1167 h_scroll_cursor_left_edge: register_simple(
1168 registry,
1169 "action:h-scroll-cursor-left-edge",
1170 "Vim's `zs`: scroll so the cursor's column sits at the left edge.",
1171 AppEffect::HorizontalScroll(HScroll::CursorToEdge { end: false }),
1172 ),
1173 h_scroll_cursor_right_edge: register_simple(
1174 registry,
1175 "action:h-scroll-cursor-right-edge",
1176 "Vim's `ze`: scroll so the cursor's column sits at the right edge.",
1177 AppEffect::HorizontalScroll(HScroll::CursorToEdge { end: true }),
1178 ),
1179 join_lines_with_space: register_simple(
1180 registry,
1181 "action:join-lines-with-space",
1182 "Vim's `J`: join the current line with the next using a single space.",
1183 AppEffect::JoinLines { with_space: true },
1184 ),
1185 join_lines_bare: register_simple(
1186 registry,
1187 "action:join-lines-bare",
1188 "Vim's `gJ`: join the current line with the next without inserting a space.",
1189 AppEffect::JoinLines { with_space: false },
1190 ),
1191 find_repeat_forward: register_simple(
1192 registry,
1193 "action:find-repeat-forward",
1194 "Vim's `;`: repeat the most recent f/F/t/T find in the same direction.",
1195 AppEffect::FindRepeat { reverse: false },
1196 ),
1197 find_repeat_reverse: register_simple(
1198 registry,
1199 "action:find-repeat-reverse",
1200 "Vim's `,`: repeat the most recent f/F/t/T find in the reverse direction.",
1201 AppEffect::FindRepeat { reverse: true },
1202 ),
1203 insert_newline: register_simple(
1204 registry,
1205 "action:insert-newline",
1206 "Insert / Replace mode's `<CR>`: insert a literal newline at the cursor.",
1207 AppEffect::InsertNewline,
1208 ),
1209 insert_tab: register_simple(
1210 registry,
1211 "action:insert-tab",
1212 "Insert mode's `<Tab>`: insert a literal tab at the cursor.",
1213 AppEffect::InsertTab,
1214 ),
1215 overwrite_char: register_action(
1216 registry,
1217 "action:overwrite-char",
1218 "Replace mode's bare-printable wildcard: overwrite the byte at the cursor with the captured char.",
1219 captured_char_action(|c| Some(AppEffect::OverwriteChar(c))),
1220 ),
1221 set_mark: register_action(
1222 registry,
1223 "action:set-mark",
1224 "Vim's `m<X>`: set mark `<X>` at the cursor (alphanumeric only).",
1225 captured_char_action(|c| {
1226 if c.is_ascii_alphanumeric() {
1227 Some(AppEffect::SetMark(c))
1228 } else {
1229 None
1230 }
1231 }),
1232 ),
1233 jump_to_mark_line: register_action(
1234 registry,
1235 "action:jump-to-mark-line",
1236 "Vim's `'<X>`: jump cursor to the line of mark `<X>` (alphanumeric only).",
1237 captured_char_action(|c| {
1238 if c.is_ascii_alphanumeric() {
1239 Some(AppEffect::JumpToMarkLine(c))
1240 } else {
1241 None
1242 }
1243 }),
1244 ),
1245 jump_to_mark_exact: register_action(
1246 registry,
1247 "action:jump-to-mark-exact",
1248 "Vim's `` `<X> ``: jump cursor to the exact position of mark `<X>`.",
1249 captured_char_action(|c| {
1250 if c.is_ascii_alphanumeric() {
1251 Some(AppEffect::JumpToMarkExact(c))
1252 } else {
1253 None
1254 }
1255 }),
1256 ),
1257 select_register: register_action(
1258 registry,
1259 "action:select-register",
1260 "Vim's `\"<X>`: select named register `<X>` for the next yank / paste / delete.",
1261 captured_char_action(|c| Register::from_input_char(c).map(AppEffect::SelectRegister)),
1262 ),
1263 start_macro_record: register_action(
1264 registry,
1265 "action:start-macro-record",
1266 "Vim's `q<X>`: start recording a macro into register `<X>` (alphanumeric only).",
1267 captured_char_action(|c| {
1268 if c.is_ascii_alphanumeric() {
1269 Some(AppEffect::StartMacroRecord(c))
1270 } else {
1271 None
1272 }
1273 }),
1274 ),
1275 play_macro: register_action(
1276 registry,
1277 "action:play-macro",
1278 "Vim's `@<X>`: play the macro stored in register `<X>`. `@@` replays the most recent macro.",
1279 captured_char_action(|c| {
1280 if c == '@' {
1281 Some(AppEffect::PlayLastMacro)
1282 } else if c.is_ascii_alphanumeric() {
1283 Some(AppEffect::PlayMacro(c))
1284 } else {
1285 None
1286 }
1287 }),
1288 ),
1289 absorb_operator_delete: register_operator_prefix(
1290 registry,
1291 "action:absorb-operator-delete",
1292 "Vim's `d`: arm operator-pending for delete.",
1293 builtins.delete,
1294 ),
1295 absorb_operator_change: register_operator_prefix(
1296 registry,
1297 "action:absorb-operator-change",
1298 "Vim's `c`: arm operator-pending for change.",
1299 builtins.change,
1300 ),
1301 absorb_operator_yank: register_operator_prefix(
1302 registry,
1303 "action:absorb-operator-yank",
1304 "Vim's `y`: arm operator-pending for yank.",
1305 builtins.yank,
1306 ),
1307 absorb_operator_indent_right: register_operator_prefix(
1308 registry,
1309 "action:absorb-operator-indent-right",
1310 "Vim's `>`: arm operator-pending for indent-right.",
1311 builtins.indent_right,
1312 ),
1313 absorb_operator_indent_left: register_operator_prefix(
1314 registry,
1315 "action:absorb-operator-indent-left",
1316 "Vim's `<`: arm operator-pending for indent-left.",
1317 builtins.indent_left,
1318 ),
1319 absorb_operator_reindent: register_operator_prefix(
1320 registry,
1321 "action:absorb-operator-reindent",
1322 "Vim's `=`: arm operator-pending for reindent.",
1323 builtins.reindent,
1324 ),
1325 absorb_operator_reflow: register_operator_prefix(
1331 registry,
1332 "action:absorb-operator-reflow",
1333 "Vim's `gq` / `gw`: arm operator-pending for reflow.",
1334 builtins.reflow,
1335 ),
1336 absorb_operator_upper: register_operator_prefix(
1337 registry,
1338 "action:absorb-operator-upper",
1339 "Vim's `gU`: arm operator-pending for uppercase.",
1340 builtins.upper,
1341 ),
1342 absorb_operator_lower: register_operator_prefix(
1343 registry,
1344 "action:absorb-operator-lower",
1345 "Vim's `gu`: arm operator-pending for lowercase.",
1346 builtins.lower,
1347 ),
1348 absorb_operator_toggle_case: register_operator_prefix(
1349 registry,
1350 "action:absorb-operator-toggle-case",
1351 "Vim's `g~`: arm operator-pending for toggle-case.",
1352 builtins.toggle_case,
1353 ),
1354 absorb_operator_search: register_operator_prefix(
1355 registry,
1356 "action:absorb-operator-search",
1357 "Lattice's `g/`: arm operator-pending for project-search.",
1358 builtins.search,
1359 ),
1360 split_pane_horizontal: register_simple(
1361 registry,
1362 "action:split-pane-horizontal",
1363 "Vim's `<C-w>s`: split the active pane horizontally.",
1364 AppEffect::SplitPaneHorizontal,
1365 ),
1366 split_pane_vertical: register_simple(
1367 registry,
1368 "action:split-pane-vertical",
1369 "Vim's `<C-w>v`: split the active pane vertically.",
1370 AppEffect::SplitPaneVertical,
1371 ),
1372 close_pane: register_simple(
1373 registry,
1374 "action:close-pane",
1375 "Vim's `<C-w>c`: close the active pane.",
1376 AppEffect::ClosePane,
1377 ),
1378 only_pane: register_simple(
1379 registry,
1380 "action:only-pane",
1381 "Vim's `<C-w>o` / `:only`: close every pane except the active one.",
1382 AppEffect::OnlyPane,
1383 ),
1384 toggle_zoom_pane: register_simple(
1385 registry,
1386 "action:toggle-zoom-pane",
1387 "`<C-w>z` / `:zoom-pane`: toggle zoom on the active pane.",
1388 AppEffect::ToggleZoomPane,
1389 ),
1390 navigate_pane_left: register_simple(
1391 registry,
1392 "action:navigate-pane-left",
1393 "Vim's `<C-w>h`: move focus to the pane on the left.",
1394 AppEffect::NavigatePane(PaneDirection::Left),
1395 ),
1396 navigate_pane_down: register_simple(
1397 registry,
1398 "action:navigate-pane-down",
1399 "Vim's `<C-w>j`: move focus to the pane below.",
1400 AppEffect::NavigatePane(PaneDirection::Down),
1401 ),
1402 navigate_pane_up: register_simple(
1403 registry,
1404 "action:navigate-pane-up",
1405 "Vim's `<C-w>k`: move focus to the pane above.",
1406 AppEffect::NavigatePane(PaneDirection::Up),
1407 ),
1408 navigate_pane_right: register_simple(
1409 registry,
1410 "action:navigate-pane-right",
1411 "Vim's `<C-w>l`: move focus to the pane on the right.",
1412 AppEffect::NavigatePane(PaneDirection::Right),
1413 ),
1414 next_pane: register_simple(
1415 registry,
1416 "action:next-pane",
1417 "Vim's `<C-w>w`: cycle focus to the next pane.",
1418 AppEffect::NextPane,
1419 ),
1420 prev_pane: register_simple(
1421 registry,
1422 "action:prev-pane",
1423 "Vim's `<C-w>W`: cycle focus to the previous pane.",
1424 AppEffect::PrevPane,
1425 ),
1426 equalize_panes: register_simple(
1428 registry,
1429 "action:equalize-panes",
1430 "Vim's `<C-w>=`: reset every split's ratio to 0.5.",
1431 AppEffect::EqualizePanes,
1432 ),
1433 grow_pane_height: register_simple(
1434 registry,
1435 "action:grow-pane-height",
1436 "Vim's `<C-w>+`: grow the active pane vertically.",
1437 AppEffect::GrowPaneHeight,
1438 ),
1439 shrink_pane_height: register_simple(
1440 registry,
1441 "action:shrink-pane-height",
1442 "Vim's `<C-w>-`: shrink the active pane vertically.",
1443 AppEffect::ShrinkPaneHeight,
1444 ),
1445 grow_pane_width: register_simple(
1446 registry,
1447 "action:grow-pane-width",
1448 "Vim's `<C-w>>`: grow the active pane horizontally.",
1449 AppEffect::GrowPaneWidth,
1450 ),
1451 shrink_pane_width: register_simple(
1452 registry,
1453 "action:shrink-pane-width",
1454 "Vim's `<C-w><`: shrink the active pane horizontally.",
1455 AppEffect::ShrinkPaneWidth,
1456 ),
1457 picker_accept_in_split: register_simple(
1460 registry,
1461 "action:picker-accept-in-split",
1462 "Picker `<C-s>`: accept candidate in a horizontal split.",
1463 AppEffect::PickerAcceptInSplit,
1464 ),
1465 picker_accept_in_vsplit: register_simple(
1466 registry,
1467 "action:picker-accept-in-vsplit",
1468 "Picker `<C-v>`: accept candidate in a vertical split.",
1469 AppEffect::PickerAcceptInVSplit,
1470 ),
1471 picker_accept_in_tab: register_simple(
1472 registry,
1473 "action:picker-accept-in-tab",
1474 "Picker `<C-t>`: accept candidate in a new tab.",
1475 AppEffect::PickerAcceptInTab,
1476 ),
1477 next_tab: register_simple(
1478 registry,
1479 "action:next-tab",
1480 "Vim's `gt`: switch to the next tab.",
1481 AppEffect::NextTab,
1482 ),
1483 prev_tab: register_simple(
1484 registry,
1485 "action:prev-tab",
1486 "Vim's `gT`: switch to the previous tab.",
1487 AppEffect::PrevTab,
1488 ),
1489 new_tab: register_simple(
1490 registry,
1491 "action:new-tab",
1492 "`:tabnew`: open a new tab.",
1493 AppEffect::NewTab,
1494 ),
1495 close_tab: register_simple(
1496 registry,
1497 "action:close-tab",
1498 "`:tabclose`: close the active tab.",
1499 AppEffect::CloseTab,
1500 ),
1501 only_tab: register_simple(
1502 registry,
1503 "action:only-tab",
1504 "`:tabonly`: close every tab except the active one.",
1505 AppEffect::OnlyTab,
1506 ),
1507 quit: register_simple(
1508 registry,
1509 "action:quit",
1510 "Graceful editor shutdown.",
1511 AppEffect::Quit,
1512 ),
1513 cancel: register_simple(
1514 registry,
1515 "action:cancel",
1516 "`<C-c>` (`<C-g>` with emacs-keys): cancel the in-flight \
1517 foreground operation and return to Normal mode.",
1518 AppEffect::Cancel,
1519 ),
1520 move_tab: register_simple(
1525 registry,
1526 "action:move-tab",
1527 "`:tabmove [N]`: move the active tab to position N (default last).",
1528 AppEffect::MoveTab(0),
1529 ),
1530 move_pane_to_new_tab: register_simple(
1531 registry,
1532 "action:move-pane-to-new-tab",
1533 "`<C-w>T`: move the active pane to a fresh tab.",
1534 AppEffect::MovePaneToNewTab,
1535 ),
1536 completion_next: register_simple(
1537 registry,
1538 "action:completion-next",
1539 "Completion-popup `<C-n>` / `<Down>`: focus the next entry.",
1540 AppEffect::CompletionNext,
1541 ),
1542 completion_prev: register_simple(
1543 registry,
1544 "action:completion-prev",
1545 "Completion-popup `<C-p>` / `<Up>`: focus the previous entry.",
1546 AppEffect::CompletionPrev,
1547 ),
1548 completion_accept: register_simple(
1549 registry,
1550 "action:completion-accept",
1551 "Completion-popup `<C-y>` / `<Tab>` / `<CR>`: accept the focused candidate.",
1552 AppEffect::CompletionAccept,
1553 ),
1554 completion_cancel: register_simple(
1555 registry,
1556 "action:completion-cancel",
1557 "Completion-popup `<C-e>`: cancel the popup, stay in Insert.",
1558 AppEffect::CompletionCancel,
1559 ),
1560 completion_cancel_and_exit_insert: register_simple(
1561 registry,
1562 "action:completion-cancel-and-exit-insert",
1563 "Completion-popup `<Esc>`: cancel the popup and exit Insert.",
1564 AppEffect::CompletionCancelAndExitInsert,
1565 ),
1566 completion_toggle_docs: register_simple(
1567 registry,
1568 "action:completion-toggle-docs",
1569 "Completion-popup `<C-d>`: toggle the doc popup.",
1570 AppEffect::CompletionToggleDocs,
1571 ),
1572 completion_docs_scroll_down: register_simple(
1573 registry,
1574 "action:completion-docs-scroll-down",
1575 "Completion-popup `<C-f>`: scroll the doc popup down.",
1576 AppEffect::CompletionDocsScrollDown,
1577 ),
1578 completion_docs_scroll_up: register_simple(
1579 registry,
1580 "action:completion-docs-scroll-up",
1581 "Completion-popup `<C-b>`: scroll the doc popup up.",
1582 AppEffect::CompletionDocsScrollUp,
1583 ),
1584 completion_accept_then_insert: register_action(
1585 registry,
1586 "action:completion-accept-then-insert",
1587 "Completion-popup bare-printable wildcard: accept then insert the captured char (control chars filtered).",
1588 captured_char_action(|c| {
1589 if c.is_control() {
1594 None
1595 } else {
1596 Some(AppEffect::CompletionAcceptThenInsert(c))
1597 }
1598 }),
1599 ),
1600 insert_register: register_action(
1601 registry,
1602 "action:insert-register",
1603 "Insert a register's contents at the cursor (vim's `<C-r>{reg}`).",
1604 captured_char_action(|c| Some(AppEffect::InsertRegister(c))),
1605 ),
1606 open_yank_picker: register_simple(
1607 registry,
1608 "action:open-yank-picker",
1609 "Open the yank-ring picker, inserting the pick into whichever surface it was opened from.",
1610 AppEffect::OpenYankPicker,
1611 ),
1612 open_arg_picker: register_simple(
1613 registry,
1614 "action:open-arg-picker",
1615 "Open the picker registered for the `:`-line argument under the cursor (vim's omni-completion chord).",
1616 AppEffect::OpenArgPicker,
1617 ),
1618 completion_filter_to_source: register_action(
1619 registry,
1620 "action:completion-filter-to-source",
1621 "Completion-popup filter chord: restrict candidates to a single source (Args::String = source-id).",
1622 captured_string_action(|id| {
1623 if id.is_empty() {
1624 None
1625 } else {
1626 Some(AppEffect::CompletionFilterToSource(id))
1627 }
1628 }),
1629 ),
1630 completion_filter_clear: register_simple(
1631 registry,
1632 "action:completion-filter-clear",
1633 "Completion-popup `<C-Space>`: clear the active source filter.",
1634 AppEffect::CompletionFilterClear,
1635 ),
1636 snippet_next_placeholder: register_simple(
1638 registry,
1639 "action:snippet-next-placeholder",
1640 "Active-snippet `<Tab>`: jump to the next placeholder.",
1641 AppEffect::SnippetNextPlaceholder,
1642 ),
1643 snippet_prev_placeholder: register_simple(
1644 registry,
1645 "action:snippet-prev-placeholder",
1646 "Active-snippet `<S-Tab>`: jump to the previous placeholder.",
1647 AppEffect::SnippetPrevPlaceholder,
1648 ),
1649 snippet_leave: registry.register_action(
1656 "action:snippet-leave",
1657 "Active-snippet `<Esc>`: exit the snippet (mode-owned; \
1658 `active-snippet-mode`'s handler clears the session + enters Normal).",
1659 ActionSpec {
1660 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
1661 args_schema: vec![],
1662 },
1663 ),
1664
1665 search_refresh: register_simple(
1666 registry,
1667 "action:search-refresh",
1668 "project-search-mode `gr`: re-run the scan with the view's current query.",
1669 AppEffect::SearchRefresh,
1670 ),
1671 compilation_recompile: register_simple(
1672 registry,
1673 "action:compilation-recompile",
1674 "compilation-mode `gr`: recompile — re-run the last compilation command.",
1675 AppEffect::CompileRun { cmdline: None },
1676 ),
1677 compilation_jump: registry.register_action(
1685 "action:compilation-jump",
1686 "compilation-mode `<CR>`: jump to the source location under the cursor \
1687 (mode-owned; the handler parses the line + syncs the error list index).",
1688 ActionSpec {
1689 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
1690 args_schema: vec![],
1691 },
1692 ),
1693 multibuffer_jump_to_source: registry.register_action(
1694 "action:multibuffer-jump-to-source",
1695 "multibuffer-mode `<CR>`: jump to the source file/row of the excerpt under cursor \
1696 (generic; the handler resolves source + path through the multibuffer view).",
1697 ActionSpec {
1698 apply: Arc::new(|_ctx| Ok(lattice_grammar::Effect::None)),
1699 args_schema: vec![],
1700 },
1701 ),
1702 }
1703}
1704
1705fn register_operator_prefix(
1710 registry: &mut CommandRegistry,
1711 name: &str,
1712 doc: &str,
1713 op: OperatorId,
1714) -> CommandId {
1715 registry.register_action(
1716 name,
1717 doc,
1718 ActionSpec {
1719 apply: Arc::new(move |_| Ok(Effect::AppAction(AppEffect::AbsorbOperatorPrefix(op)))),
1720 args_schema: vec![],
1721 },
1722 )
1723}
1724
1725fn captured_char_action(
1738 decide: impl Fn(char) -> Option<AppEffect> + Send + Sync + 'static,
1739) -> ActionSpec {
1740 ActionSpec {
1741 apply: Arc::new(move |ctx| {
1742 let c = match ctx.args {
1743 Args::Char(c) => c,
1744 _ => return Ok(Effect::None),
1745 };
1746 Ok(match decide(c) {
1747 Some(eff) => Effect::AppAction(eff),
1748 None => Effect::None,
1749 })
1750 }),
1751 args_schema: vec![],
1752 }
1753}
1754
1755fn captured_string_action(
1761 decide: impl Fn(String) -> Option<AppEffect> + Send + Sync + 'static,
1762) -> ActionSpec {
1763 ActionSpec {
1764 apply: Arc::new(move |ctx| {
1765 let s = match &ctx.args {
1766 Args::String(s) => s.clone(),
1767 _ => return Ok(Effect::None),
1768 };
1769 Ok(match decide(s) {
1770 Some(eff) => Effect::AppAction(eff),
1771 None => Effect::None,
1772 })
1773 }),
1774 args_schema: vec![],
1775 }
1776}
1777
1778fn register_action(
1783 registry: &mut CommandRegistry,
1784 name: &str,
1785 doc: &str,
1786 spec: ActionSpec,
1787) -> CommandId {
1788 registry.register_action(name, doc, spec)
1789}
1790
1791fn register_simple(
1797 registry: &mut CommandRegistry,
1798 name: &str,
1799 doc: &str,
1800 effect: AppEffect,
1801) -> CommandId {
1802 registry.register_action(
1803 name,
1804 doc,
1805 ActionSpec {
1806 apply: Arc::new(move |_ctx| Ok(lattice_grammar::Effect::AppAction(effect.clone()))),
1807 args_schema: vec![],
1808 },
1809 )
1810}
1811
1812#[cfg(test)]
1817mod tests {
1818 #![allow(clippy::unwrap_used, clippy::panic)]
1819 use super::*;
1820 use lattice_grammar::CancellationToken;
1821 use lattice_grammar::CommandInvocation;
1822 use lattice_grammar::Effect;
1823 use lattice_grammar::dispatcher::execute;
1824
1825 #[test]
1826 fn populate_registers_every_field_into_registry() {
1827 let mut registry = CommandRegistry::new();
1828 let builtins = lattice_grammar::builtins::populate(&mut registry);
1829 let ids = populate(&mut registry, &builtins);
1830 for (id, expected_name) in [
1833 (ids.match_bracket, "action:match-bracket"),
1834 (ids.toggle_case_at_cursor, "action:toggle-case-at-cursor"),
1835 (ids.open_line_below, "action:open-line-below"),
1836 (ids.open_line_above, "action:open-line-above"),
1837 (ids.lsp_hover_request, "action:lsp-hover"),
1838 (ids.search_next, "action:search-next"),
1839 (ids.search_previous, "action:search-previous"),
1840 (ids.error_next, "action:error-next"),
1841 (ids.error_prev, "action:error-prev"),
1842 (ids.error_first, "action:error-first"),
1843 (ids.error_last, "action:error-last"),
1844 (ids.error_next_file, "action:error-next-file"),
1845 (ids.error_prev_file, "action:error-prev-file"),
1846 (ids.jump_history_back, "action:jump-history-back"),
1847 (ids.jump_history_forward, "action:jump-history-forward"),
1848 (ids.walk_mark_history_back, "action:walk-mark-history-back"),
1849 (
1850 ids.walk_mark_history_forward,
1851 "action:walk-mark-history-forward",
1852 ),
1853 (ids.tag_stack_pop, "action:tag-stack-pop"),
1854 (ids.open_fold_at_cursor, "action:open-fold-at-cursor"),
1855 (ids.close_fold_at_cursor, "action:close-fold-at-cursor"),
1856 (ids.toggle_fold_at_cursor, "action:toggle-fold-at-cursor"),
1857 (ids.open_all_folds, "action:open-all-folds"),
1858 (ids.close_all_folds, "action:close-all-folds"),
1859 (ids.cycle_fold_at_cursor, "action:fold-cycle"),
1860 (ids.cycle_folds_global, "action:fold-cycle-global"),
1861 (ids.goto_parent_fold, "action:fold-goto-parent"),
1862 (ids.delete_fold_at_cursor, "action:delete-fold-at-cursor"),
1863 (ids.open_folds_recursively, "action:open-folds-recursively"),
1864 (
1865 ids.close_folds_recursively,
1866 "action:close-folds-recursively",
1867 ),
1868 (
1869 ids.delete_folds_recursively,
1870 "action:delete-folds-recursively",
1871 ),
1872 (ids.goto_next_fold, "action:goto-next-fold"),
1873 (ids.goto_prev_fold, "action:goto-prev-fold"),
1874 (ids.toggle_fold_enable, "action:toggle-fold-enable"),
1875 (ids.undo, "action:undo"),
1876 (ids.redo, "action:redo"),
1877 (ids.repeat_last_change, "action:repeat-last-change"),
1878 (ids.page_down, "action:page-down"),
1879 (ids.half_page_down, "action:half-page-down"),
1880 (ids.half_page_up, "action:half-page-up"),
1881 (ids.page_up, "action:page-up"),
1882 (ids.scroll_line_up, "action:scroll-line-up"),
1883 (ids.scroll_line_down, "action:scroll-line-down"),
1884 (ids.redraw_screen, "action:redraw-screen"),
1885 (ids.open_command_picker, "action:open-command-picker"),
1886 (ids.open_history_picker, "action:open-history-picker"),
1887 (
1888 ids.open_search_history_picker,
1889 "action:open-search-history-picker",
1890 ),
1891 (ids.enter_command_line, "action:enter-command-line"),
1892 (ids.command_line_submit, "action:command-line-submit"),
1893 (ids.command_line_cancel, "action:command-line-cancel"),
1894 (
1895 ids.command_line_history_prev,
1896 "action:command-line-history-prev",
1897 ),
1898 (
1899 ids.command_line_history_next,
1900 "action:command-line-history-next",
1901 ),
1902 (ids.command_line_complete, "action:command-line-complete"),
1903 (
1904 ids.command_line_complete_prev,
1905 "action:command-line-complete-prev",
1906 ),
1907 (
1908 ids.command_line_describe_under_cursor,
1909 "action:command-line-describe-under-cursor",
1910 ),
1911 (
1912 ids.command_line_toggle_expand,
1913 "action:command-line-toggle-expand",
1914 ),
1915 (ids.search_line_submit, "action:search-line-submit"),
1916 (ids.search_line_cancel, "action:search-line-cancel"),
1917 (ids.search_line_backspace, "action:search-line-backspace"),
1918 (
1919 ids.search_line_history_prev,
1920 "action:search-line-history-prev",
1921 ),
1922 (
1923 ids.search_line_history_next,
1924 "action:search-line-history-next",
1925 ),
1926 (
1927 ids.search_line_toggle_expand,
1928 "action:search-line-toggle-expand",
1929 ),
1930 (ids.prompt_line_submit, "action:prompt-line-submit"),
1931 (ids.prompt_line_cancel, "action:prompt-line-cancel"),
1932 (ids.oil_navigate_up, "action:oil-navigate-up"),
1933 (ids.reselect_last_visual, "action:reselect-last-visual"),
1934 (ids.paste_after, "action:paste-after"),
1935 (ids.paste_before, "action:paste-before"),
1936 (ids.lsp_definition_request, "action:lsp-definition"),
1937 (ids.lsp_declaration_request, "action:lsp-declaration"),
1938 (
1939 ids.lsp_type_definition_request,
1940 "action:lsp-type-definition",
1941 ),
1942 (ids.lsp_implementation_request, "action:lsp-implementation"),
1943 (ids.lsp_references_request, "action:lsp-references"),
1944 (ids.lsp_follow_link_at_cursor, "action:lsp-follow-link"),
1945 (ids.enter_append, "action:enter-append"),
1946 (
1947 ids.enter_insert_first_non_blank,
1948 "action:enter-insert-first-non-blank",
1949 ),
1950 (
1951 ids.enter_append_end_of_line,
1952 "action:enter-append-end-of-line",
1953 ),
1954 (ids.display_line_down, "action:display-line-down"),
1955 (ids.display_line_up, "action:display-line-up"),
1956 (ids.display_line_start, "action:display-line-start"),
1957 (ids.display_line_end, "action:display-line-end"),
1958 (
1959 ids.create_fold_from_visual,
1960 "action:create-fold-from-visual",
1961 ),
1962 (ids.delete_char_backward, "action:delete-char-backward"),
1963 (ids.completion_trigger, "action:completion-trigger"),
1964 (ids.snippet_expand, "action:snippet-expand"),
1965 (ids.lsp_diagnostic_popup, "action:lsp-diagnostic-popup"),
1966 (ids.exit_visual, "action:exit-visual"),
1967 (ids.swap_visual_ends, "action:swap-visual-ends"),
1968 (ids.replace_undo_last, "action:replace-undo-last"),
1969 (ids.enter_mode_insert, "action:enter-mode-insert"),
1970 (ids.enter_mode_normal, "action:enter-mode-normal"),
1971 (ids.enter_mode_replace, "action:enter-mode-replace"),
1972 (ids.enter_visual_charwise, "action:enter-visual-charwise"),
1973 (ids.enter_visual_linewise, "action:enter-visual-linewise"),
1974 (ids.enter_visual_blockwise, "action:enter-visual-blockwise"),
1975 (ids.enter_search_forward, "action:enter-search-forward"),
1976 (ids.enter_search_backward, "action:enter-search-backward"),
1977 (
1978 ids.search_word_under_cursor_forward,
1979 "action:search-word-under-cursor-forward",
1980 ),
1981 (
1982 ids.search_word_under_cursor_backward,
1983 "action:search-word-under-cursor-backward",
1984 ),
1985 (ids.jump_viewport_top, "action:jump-viewport-top"),
1986 (ids.jump_viewport_middle, "action:jump-viewport-middle"),
1987 (ids.jump_viewport_bottom, "action:jump-viewport-bottom"),
1988 (ids.scroll_cursor_to_top, "action:scroll-cursor-to-top"),
1989 (
1990 ids.scroll_cursor_to_center,
1991 "action:scroll-cursor-to-center",
1992 ),
1993 (
1994 ids.scroll_cursor_to_bottom,
1995 "action:scroll-cursor-to-bottom",
1996 ),
1997 (ids.join_lines_with_space, "action:join-lines-with-space"),
1998 (ids.join_lines_bare, "action:join-lines-bare"),
1999 (ids.find_repeat_forward, "action:find-repeat-forward"),
2000 (ids.find_repeat_reverse, "action:find-repeat-reverse"),
2001 (ids.insert_newline, "action:insert-newline"),
2002 (ids.insert_tab, "action:insert-tab"),
2003 (ids.overwrite_char, "action:overwrite-char"),
2004 (ids.set_mark, "action:set-mark"),
2005 (ids.jump_to_mark_line, "action:jump-to-mark-line"),
2006 (ids.jump_to_mark_exact, "action:jump-to-mark-exact"),
2007 (ids.select_register, "action:select-register"),
2008 (ids.start_macro_record, "action:start-macro-record"),
2009 (ids.play_macro, "action:play-macro"),
2010 (ids.absorb_operator_delete, "action:absorb-operator-delete"),
2011 (ids.absorb_operator_change, "action:absorb-operator-change"),
2012 (ids.absorb_operator_yank, "action:absorb-operator-yank"),
2013 (
2014 ids.absorb_operator_indent_right,
2015 "action:absorb-operator-indent-right",
2016 ),
2017 (
2018 ids.absorb_operator_indent_left,
2019 "action:absorb-operator-indent-left",
2020 ),
2021 (
2022 ids.absorb_operator_reindent,
2023 "action:absorb-operator-reindent",
2024 ),
2025 (ids.absorb_operator_reflow, "action:absorb-operator-reflow"),
2026 (ids.absorb_operator_upper, "action:absorb-operator-upper"),
2027 (ids.absorb_operator_lower, "action:absorb-operator-lower"),
2028 (
2029 ids.absorb_operator_toggle_case,
2030 "action:absorb-operator-toggle-case",
2031 ),
2032 (ids.split_pane_horizontal, "action:split-pane-horizontal"),
2033 (ids.split_pane_vertical, "action:split-pane-vertical"),
2034 (ids.close_pane, "action:close-pane"),
2035 (ids.only_pane, "action:only-pane"),
2036 (ids.toggle_zoom_pane, "action:toggle-zoom-pane"),
2037 (ids.navigate_pane_left, "action:navigate-pane-left"),
2038 (ids.navigate_pane_down, "action:navigate-pane-down"),
2039 (ids.navigate_pane_up, "action:navigate-pane-up"),
2040 (ids.navigate_pane_right, "action:navigate-pane-right"),
2041 (ids.next_pane, "action:next-pane"),
2042 (ids.prev_pane, "action:prev-pane"),
2043 (ids.equalize_panes, "action:equalize-panes"),
2045 (ids.grow_pane_height, "action:grow-pane-height"),
2046 (ids.shrink_pane_height, "action:shrink-pane-height"),
2047 (ids.grow_pane_width, "action:grow-pane-width"),
2048 (ids.shrink_pane_width, "action:shrink-pane-width"),
2049 (ids.picker_accept_in_split, "action:picker-accept-in-split"),
2052 (
2053 ids.picker_accept_in_vsplit,
2054 "action:picker-accept-in-vsplit",
2055 ),
2056 (ids.picker_accept_in_tab, "action:picker-accept-in-tab"),
2057 (ids.next_tab, "action:next-tab"),
2058 (ids.prev_tab, "action:prev-tab"),
2059 (ids.new_tab, "action:new-tab"),
2060 (ids.close_tab, "action:close-tab"),
2061 (ids.only_tab, "action:only-tab"),
2062 (ids.move_tab, "action:move-tab"),
2063 (ids.move_pane_to_new_tab, "action:move-pane-to-new-tab"),
2064 (ids.completion_next, "action:completion-next"),
2065 (ids.completion_prev, "action:completion-prev"),
2066 (ids.completion_accept, "action:completion-accept"),
2067 (ids.completion_cancel, "action:completion-cancel"),
2068 (
2069 ids.completion_cancel_and_exit_insert,
2070 "action:completion-cancel-and-exit-insert",
2071 ),
2072 (ids.completion_toggle_docs, "action:completion-toggle-docs"),
2073 (
2074 ids.completion_docs_scroll_down,
2075 "action:completion-docs-scroll-down",
2076 ),
2077 (
2078 ids.completion_docs_scroll_up,
2079 "action:completion-docs-scroll-up",
2080 ),
2081 (
2082 ids.completion_accept_then_insert,
2083 "action:completion-accept-then-insert",
2084 ),
2085 (ids.insert_register, "action:insert-register"),
2086 (ids.open_yank_picker, "action:open-yank-picker"),
2087 (ids.open_arg_picker, "action:open-arg-picker"),
2088 (
2089 ids.completion_filter_to_source,
2090 "action:completion-filter-to-source",
2091 ),
2092 (
2093 ids.completion_filter_clear,
2094 "action:completion-filter-clear",
2095 ),
2096 (
2097 ids.snippet_next_placeholder,
2098 "action:snippet-next-placeholder",
2099 ),
2100 (
2101 ids.snippet_prev_placeholder,
2102 "action:snippet-prev-placeholder",
2103 ),
2104 (ids.snippet_leave, "action:snippet-leave"),
2105 ] {
2106 let spec = registry
2107 .lookup(id)
2108 .unwrap_or_else(|| panic!("missing registry entry for `{expected_name}`"));
2109 assert_eq!(spec.name, expected_name);
2110 }
2111 }
2112
2113 #[test]
2114 fn dispatch_returns_app_action_effect() {
2115 let mut registry = CommandRegistry::new();
2116 let builtins = lattice_grammar::builtins::populate(&mut registry);
2117 let ids = populate(&mut registry, &builtins);
2118 let mut doc = lattice_core::Document::empty();
2119 let inv = CommandInvocation::of(ids.match_bracket);
2120 let eff = execute(
2121 ®istry,
2122 &mut doc,
2123 lattice_core::BufferId(0),
2124 lattice_protocol::position::Position::ZERO,
2125 inv,
2126 &CancellationToken::never(),
2127 )
2128 .unwrap();
2129 match eff {
2130 Effect::AppAction(AppEffect::MatchBracket) => {}
2131 other => panic!("expected MatchBracket, got {other:?}"),
2132 }
2133 }
2134
2135 #[test]
2141 fn captured_char_specs_validate() {
2142 let mut registry = CommandRegistry::new();
2143 let builtins = lattice_grammar::builtins::populate(&mut registry);
2144 let ids = populate(&mut registry, &builtins);
2145 let mut doc = lattice_core::Document::empty();
2146 let cancel = CancellationToken::never();
2147 let pos = lattice_protocol::position::Position::ZERO;
2148
2149 let dispatch_with_char = |id: lattice_protocol::ids::CommandId,
2150 c: char,
2151 registry: &CommandRegistry,
2152 doc: &mut lattice_core::Document|
2153 -> Effect {
2154 execute(
2155 registry,
2156 doc,
2157 lattice_core::BufferId(0),
2158 pos,
2159 CommandInvocation::of(id).with_args(Args::Char(c)),
2160 &cancel,
2161 )
2162 .unwrap()
2163 };
2164
2165 match dispatch_with_char(ids.set_mark, 'a', ®istry, &mut doc) {
2167 Effect::AppAction(AppEffect::SetMark('a')) => {}
2168 other => panic!("expected SetMark('a'), got {other:?}"),
2169 }
2170 match dispatch_with_char(ids.set_mark, '!', ®istry, &mut doc) {
2171 Effect::None => {}
2172 other => panic!("expected None for invalid mark name, got {other:?}"),
2173 }
2174
2175 match dispatch_with_char(ids.select_register, '+', ®istry, &mut doc) {
2177 Effect::AppAction(AppEffect::SelectRegister(Register::System)) => {}
2178 other => panic!("expected SelectRegister(System), got {other:?}"),
2179 }
2180 match dispatch_with_char(ids.select_register, 'a', ®istry, &mut doc) {
2181 Effect::AppAction(AppEffect::SelectRegister(Register::Named('a'))) => {}
2182 other => panic!("expected SelectRegister(Named('a')), got {other:?}"),
2183 }
2184 match dispatch_with_char(ids.select_register, '@', ®istry, &mut doc) {
2185 Effect::None => {}
2186 other => panic!("expected None for invalid register char, got {other:?}"),
2187 }
2188
2189 match dispatch_with_char(ids.play_macro, '@', ®istry, &mut doc) {
2192 Effect::AppAction(AppEffect::PlayLastMacro) => {}
2193 other => panic!("expected PlayLastMacro, got {other:?}"),
2194 }
2195 match dispatch_with_char(ids.play_macro, 'q', ®istry, &mut doc) {
2196 Effect::AppAction(AppEffect::PlayMacro('q')) => {}
2197 other => panic!("expected PlayMacro('q'), got {other:?}"),
2198 }
2199 match dispatch_with_char(ids.play_macro, '!', ®istry, &mut doc) {
2200 Effect::None => {}
2201 other => panic!("expected None for invalid macro key, got {other:?}"),
2202 }
2203
2204 match dispatch_with_char(ids.overwrite_char, '$', ®istry, &mut doc) {
2206 Effect::AppAction(AppEffect::OverwriteChar('$')) => {}
2207 other => panic!("expected OverwriteChar('$'), got {other:?}"),
2208 }
2209 }
2210}