1#[derive(Clone, Copy)]
27pub enum Handler {
28 Leaf(fn(&mut crate::editor::Editor, char)),
31 Alias(&'static str),
33 Motion,
36 Operator,
38 ObjectPrefix,
42 Prefix,
44 TextLine,
47 AbsorbChar(AbsorbKind),
49 AbsorbRegister,
51 Contextual,
53 Soon,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum AbsorbKind {
60 Replace,
61 MarkSet,
62 MarkJump,
63 Find,
64 MacroRecord,
66 MacroPlay,
68}
69
70pub struct Binding {
74 pub keys: &'static str,
75 pub desc: &'static str,
76 pub sections: &'static [&'static str],
79 pub live: bool,
81 pub id: &'static str,
83 pub handler: Handler,
84}
85
86pub const SECTIONS: &[&str] = &["normal", "visual", "insert", "leader", "git", "ex+panes"];
87
88pub const BINDINGS: &[Binding] = &[
89 Binding {
91 keys: "h j k l",
92 desc: "move (never off the line)",
93 sections: &["normal"],
94 live: true,
95 id: "move",
96 handler: Handler::Motion,
97 },
98 Binding {
99 keys: "w b e W B E",
100 desc: "word / WORD motions",
101 sections: &["normal"],
102 live: true,
103 id: "word-motions",
104 handler: Handler::Motion,
105 },
106 Binding {
107 keys: "zz zt zb",
108 desc: "center/top/bottom the cursor line",
109 sections: &["normal"],
110 live: true,
111 id: "view-place",
112 handler: Handler::Leaf(|e, k| e.view_place(k)),
113 },
114 Binding {
115 keys: "H M L",
116 desc: "top/middle/bottom visible line",
117 sections: &["normal"],
118 live: true,
119 id: "visible-jumps",
120 handler: Handler::Leaf(|e, k| e.jump_visible(k, 1)),
121 },
122 Binding {
123 keys: "ZZ",
124 desc: "write + close window",
125 sections: &["normal"],
126 live: true,
127 id: "write-quit",
128 handler: Handler::Leaf(|e, _| e.write_quit()),
129 },
130 Binding {
131 keys: "gv",
132 desc: "reselect last visual",
133 sections: &["normal"],
134 live: true,
135 id: "reselect-visual",
136 handler: Handler::Leaf(|e, _| e.reselect_visual()),
137 },
138 Binding {
139 keys: "gi",
140 desc: "insert at last insert",
141 sections: &["normal"],
142 live: true,
143 id: "insert-at-last",
144 handler: Handler::Leaf(|e, _| e.insert_at_last()),
145 },
146 Binding {
147 keys: "g;",
148 desc: "older change (changelist)",
149 sections: &["normal"],
150 live: true,
151 id: "change-back",
152 handler: Handler::Leaf(|e, _| e.change_jump(true)),
153 },
154 Binding {
155 keys: "g,",
156 desc: "newer change (changelist)",
157 sections: &["normal"],
158 live: true,
159 id: "change-forward",
160 handler: Handler::Leaf(|e, _| e.change_jump(false)),
161 },
162 Binding {
163 keys: "ge gE { }",
164 desc: "word-end back / paragraph motions",
165 sections: &["normal"],
166 live: true,
167 id: "paragraph-motions",
168 handler: Handler::Motion,
169 },
170 Binding {
171 keys: "0 $ G %",
172 desc: "line/file/pair jumps",
173 sections: &["normal"],
174 live: true,
175 id: "line-jumps",
176 handler: Handler::Motion,
177 },
178 Binding {
179 keys: "g<space>",
180 desc: "collection: open full source at caret",
181 sections: &["normal"],
182 live: true,
183 id: "collection-source",
184 handler: Handler::Leaf(|e, _| e.collection_open_source_pub()),
185 },
186 Binding {
187 keys: "gb",
188 desc: "select next occurrence of word/selection",
189 sections: &["normal", "visual"],
190 live: true,
191 id: "occurrence-next",
192 handler: Handler::Leaf(|e, _| e.occurrence_next_pub()),
193 },
194 Binding {
195 keys: "gB",
196 desc: "select all occurrences in buffer",
197 sections: &["normal", "visual"],
198 live: true,
199 id: "occurrence-all",
200 handler: Handler::Leaf(|e, _| e.occurrence_all_pub()),
201 },
202 Binding {
203 keys: "gg",
204 desc: "top of file",
205 sections: &["normal"],
206 live: true,
207 id: "top",
208 handler: Handler::Motion,
209 },
210 Binding {
211 keys: "enter",
212 desc: "line down, first non-blank (blame gutter: dive)",
213 sections: &["normal"],
214 live: true,
215 id: "enter",
216 handler: Handler::Leaf(|e, _| e.enter_pub()),
217 },
218 Binding {
219 keys: "tab",
220 desc: "jump list forward (ctrl-i)",
221 sections: &["normal"],
222 live: true,
223 id: "jump-forward",
224 handler: Handler::Leaf(|e, _| e.jump_forward()),
225 },
226 Binding {
227 keys: "ctrl-r",
228 desc: "redo",
229 sections: &["normal"],
230 live: true,
231 id: "redo",
232 handler: Handler::Leaf(|e, _| e.redo()),
233 },
234 Binding {
235 keys: "ctrl-d ctrl-u ctrl-f ctrl-b",
236 desc: "half/full page scroll (count = lines)",
237 sections: &["normal"],
238 live: true,
239 id: "scroll-pages",
240 handler: Handler::Leaf(|_, _| {}), },
242 Binding {
243 keys: "ctrl-^",
244 desc: "alternate buffer",
245 sections: &["normal"],
246 live: true,
247 id: "alternate-buffer",
248 handler: Handler::Leaf(|e, _| e.alternate_buffer()),
249 },
250 Binding {
251 keys: "q<a>",
252 desc: "record macro into register",
253 sections: &["normal"],
254 live: true,
255 id: "macro-record",
256 handler: Handler::AbsorbChar(AbsorbKind::MacroRecord),
257 },
258 Binding {
259 keys: "@<a>",
260 desc: "play macro (count repeats)",
261 sections: &["normal"],
262 live: true,
263 id: "macro-play",
264 handler: Handler::AbsorbChar(AbsorbKind::MacroPlay),
265 },
266 Binding {
267 keys: "gr",
268 desc: "references (LSP)",
269 sections: &["normal"],
270 live: true,
271 id: "references",
272 handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::References)),
273 },
274 Binding {
275 keys: "gI",
276 desc: "implementation (LSP)",
277 sections: &["normal"],
278 live: true,
279 id: "implementation",
280 handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::Implementation)),
281 },
282 Binding {
283 keys: "gy",
284 desc: "type definition (LSP)",
285 sections: &["normal"],
286 live: true,
287 id: "type-definition",
288 handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::TypeDefinition)),
289 },
290 Binding {
291 keys: "gD",
292 desc: "declaration (LSP)",
293 sections: &["normal"],
294 live: true,
295 id: "declaration",
296 handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::Declaration)),
297 },
298 Binding {
299 keys: "]d [d",
300 desc: "next/prev diagnostic",
301 sections: &["normal"],
302 live: true,
303 id: "diagnostic-jumps",
304 handler: Handler::Leaf(|e, k| e.jump_diagnostic_pub(k != '[')),
305 },
306 Binding {
307 keys: "gd",
308 desc: "goto definition (LSP)",
309 sections: &["normal"],
310 live: true,
311 id: "goto-definition",
312 handler: Handler::Leaf(|e, _| crate::editor::Editor::lsp_goto_definition_pub(e)),
313 },
314 Binding {
315 keys: "gs",
316 desc: "switch source/header (clangd)",
317 sections: &["normal"],
318 live: true,
319 id: "switch-source-header",
320 handler: Handler::Leaf(|e, _| crate::editor::Editor::lsp_switch_source_header_pub(e)),
321 },
322 Binding {
323 keys: "f<c> F<c> t<c> T<c>",
324 desc: "find/till char (candidates light up)",
325 sections: &["normal"],
326 live: true,
327 id: "find-char",
328 handler: Handler::AbsorbChar(AbsorbKind::Find),
329 },
330 Binding {
331 keys: ":",
332 desc: "ex command line",
333 sections: &["normal"],
334 live: true,
335 id: "ex-line",
336 handler: Handler::TextLine,
337 },
338 Binding {
339 keys: "/ ?",
340 desc: "literal search forward / backward (live as you type or delete)",
341 sections: &["normal"],
342 live: true,
343 id: "search",
344 handler: Handler::TextLine,
345 },
346 Binding {
347 keys: "n",
348 desc: "next match",
349 sections: &["normal"],
350 live: true,
351 id: "search-next",
352 handler: Handler::Leaf(|e, _| e.repeat_search_pub(false)),
353 },
354 Binding {
355 keys: "N",
356 desc: "previous match",
357 sections: &["normal"],
358 live: true,
359 id: "search-prev",
360 handler: Handler::Leaf(|e, _| e.repeat_search_pub(true)),
361 },
362 Binding {
363 keys: "]f [f",
364 desc: "next / prev file card (collections)",
365 sections: &["normal"],
366 live: true,
367 id: "collection-file-nav",
368 handler: Handler::Leaf(|e, k| e.collection_file_step_pub(k != '[')),
369 },
370 Binding {
371 keys: "]e [e",
372 desc: "next / prev excerpt (collections; +/- context)",
373 sections: &["normal"],
374 live: true,
375 id: "collection-excerpt-nav",
376 handler: Handler::Leaf(|e, k| e.collection_excerpt_step(k != '[')),
377 },
378 Binding {
379 keys: "]c [c",
380 desc: "next / prev git hunk",
381 sections: &["normal"],
382 live: true,
383 id: "hunk-nav",
384 handler: Handler::Leaf(|e, k| e.jump_hunk_pub(k != '[')),
385 },
386 Binding {
387 keys: "m<a>",
388 desc: "set mark at cursor",
389 sections: &["normal"],
390 live: true,
391 id: "mark-set",
392 handler: Handler::AbsorbChar(AbsorbKind::MarkSet),
393 },
394 Binding {
395 keys: "'<a> `<a>",
396 desc: "jump to mark",
397 sections: &["normal"],
398 live: true,
399 id: "mark-jump",
400 handler: Handler::AbsorbChar(AbsorbKind::MarkJump),
401 },
402 Binding {
403 keys: "* #",
404 desc: "word under cursor, forward / backward",
405 sections: &["normal"],
406 live: true,
407 id: "word-search",
408 handler: Handler::Leaf(|e, k| e.search_word_under_cursor_pub(k == '#')),
409 },
410 Binding {
411 keys: "; ,",
412 desc: "repeat find, same / reversed",
413 sections: &["normal"],
414 live: true,
415 id: "find-repeat",
416 handler: Handler::Leaf(|e, k| e.repeat_find_pub(k == ',')),
417 },
418 Binding {
419 keys: "|",
420 desc: "column motion (vim); pipe moved to space |",
421 sections: &["normal"],
422 live: true,
423 id: "column-motion",
424 handler: Handler::Motion,
425 },
426 Binding {
427 keys: "space |",
428 desc: "pipe line/selection through shell (:! runs)",
429 sections: &["leader"],
430 live: true,
431 id: "pipe-shell",
432 handler: Handler::TextLine,
433 },
434 Binding {
435 keys: "Q",
436 desc: "toggle cursor at point (multicursor)",
437 sections: &["normal"],
438 live: true,
439 id: "cursor-toggle",
440 handler: Handler::Leaf(|e, _| crate::editor::Editor::toggle_cursor(e)),
441 },
442 Binding {
444 keys: "d y c > <",
445 desc: "operators + motion/object (live preview)",
446 sections: &["normal"],
447 live: true,
448 id: "operators",
449 handler: Handler::Operator,
450 },
451 Binding {
452 keys: "dd yy cc",
453 desc: "line delete/yank/change",
454 sections: &["normal"],
455 live: true,
456 id: "line-ops",
457 handler: Handler::Operator,
458 },
459 Binding {
460 keys: "D",
461 desc: "delete to line end",
462 sections: &["normal"],
463 live: true,
464 id: "op-alias-d",
465 handler: Handler::Alias("d$"),
466 },
467 Binding {
468 keys: "C",
469 desc: "change to line end",
470 sections: &["normal"],
471 live: true,
472 id: "op-alias-c",
473 handler: Handler::Alias("c$"),
474 },
475 Binding {
476 keys: "Y",
477 desc: "yank line",
478 sections: &["normal"],
479 live: true,
480 id: "op-alias-y",
481 handler: Handler::Alias("yy"),
482 },
483 Binding {
484 keys: "s",
485 desc: "substitute char",
486 sections: &["normal"],
487 live: true,
488 id: "op-alias-s",
489 handler: Handler::Alias("cl"),
490 },
491 Binding {
492 keys: "x X",
493 desc: "delete char / char back",
494 sections: &["normal"],
495 live: true,
496 id: "char-delete",
497 handler: Handler::Leaf(|e, _| crate::editor::Editor::delete_char(e)),
498 },
499 Binding {
500 keys: "iw i\" i' i( i[ i{",
501 desc: "inner objects (quotes scan the line)",
502 sections: &["normal"],
503 live: true,
504 id: "objects",
505 handler: Handler::ObjectPrefix,
506 },
507 Binding {
508 keys: "ds\" cs\"' ysiw\"",
509 desc: "surround: delete / change / add",
510 sections: &["normal"],
511 live: true,
512 id: "surround",
513 handler: Handler::ObjectPrefix,
514 },
515 Binding {
516 keys: "i a A o O I",
517 desc: "insert (auto-indent)",
518 sections: &["normal"],
519 live: true,
520 id: "insert-entries",
521 handler: Handler::Leaf(crate::editor::Editor::insert_entry_pub),
522 },
523 Binding {
524 keys: "p P",
525 desc: "paste after / before",
526 sections: &["normal"],
527 live: true,
528 id: "paste",
529 handler: Handler::Leaf(|e, k| e.paste_named_pub(None, 1, k == 'P')),
530 },
531 Binding {
532 keys: "r<c>",
533 desc: "replace char",
534 sections: &["normal"],
535 live: true,
536 id: "replace-char",
537 handler: Handler::AbsorbChar(AbsorbKind::Replace),
538 },
539 Binding {
540 keys: "J .",
541 desc: "join lines · repeat change",
542 sections: &["normal"],
543 live: true,
544 id: "join-repeat",
545 handler: Handler::Leaf(crate::editor::Editor::join_or_repeat),
546 },
547 Binding {
548 keys: "^",
549 desc: "first non-blank",
550 sections: &["normal"],
551 live: true,
552 id: "first-non-blank",
553 handler: Handler::Motion,
554 },
555 Binding {
556 keys: "~",
557 desc: "toggle case",
558 sections: &["normal"],
559 live: true,
560 id: "toggle-case",
561 handler: Handler::Leaf(|e, _| crate::editor::Editor::toggle_case_pub(e)),
562 },
563 Binding {
564 keys: "S",
565 desc: "change line",
566 sections: &["normal"],
567 live: true,
568 id: "subst-line",
569 handler: Handler::Alias("cc"),
570 },
571 Binding {
572 keys: "u ctrl-r",
573 desc: "undo / redo (one unit per command)",
574 sections: &["normal"],
575 live: true,
576 id: "undo-redo",
577 handler: Handler::Leaf(|e, _| crate::editor::Editor::undo(e)),
578 },
579 Binding {
580 keys: "\"+y \"+p \"+P",
581 desc: "system clipboard: yank / paste after / before",
582 sections: &["normal"],
583 live: true,
584 id: "reg-clipboard",
585 handler: Handler::AbsorbRegister,
586 },
587 Binding {
588 keys: "\"xy \"xp",
589 desc: "named register: yank / paste",
590 sections: &["normal"],
591 live: true,
592 id: "reg-named",
593 handler: Handler::AbsorbRegister,
594 },
595 Binding {
596 keys: "ctrl-v",
597 desc: "visual block",
598 sections: &["normal"],
599 live: true,
600 id: "visual-block",
601 handler: Handler::Leaf(|e, _| e.enter_block_pub()),
602 },
603 Binding {
604 keys: "v V",
605 desc: "visual / visual-line",
606 sections: &["normal"],
607 live: true,
608 id: "visual-enter",
609 handler: Handler::Leaf(|e, k| e.enter_visual_pub(k)),
610 },
611 Binding {
613 keys: "d y c x > <",
614 desc: "operate on selection",
615 sections: &["visual"],
616 live: true,
617 id: "visual-ops",
618 handler: Handler::Operator,
619 },
620 Binding {
621 keys: "S<c>",
622 desc: "wrap selection in pair",
623 sections: &["visual"],
624 live: true,
625 id: "visual-surround",
626 handler: Handler::AbsorbChar(AbsorbKind::Replace),
627 },
628 Binding {
629 keys: "i<a> a<a>",
630 desc: "objects select (vi[ works)",
631 sections: &["visual"],
632 live: true,
633 id: "visual-objects",
634 handler: Handler::ObjectPrefix,
635 },
636 Binding {
637 keys: "space y",
638 desc: "yank selection → clipboard",
639 sections: &["visual"],
640 live: true,
641 id: "clip-yank",
642 handler: Handler::Leaf(|e, _| e.clipboard_yank_pub()),
643 },
644 Binding {
646 keys: "esc",
647 desc: "normal mode (session = one undo unit)",
648 sections: &["insert"],
649 live: true,
650 id: "insert-esc",
651 handler: Handler::Prefix,
652 },
653 Binding {
654 keys: "backspace",
655 desc: "delete back",
656 sections: &["insert"],
657 live: true,
658 id: "insert-bs",
659 handler: Handler::Prefix,
660 },
661 Binding {
662 keys: "enter",
663 desc: "new line (auto-indent)",
664 sections: &["insert"],
665 live: true,
666 id: "insert-enter",
667 handler: Handler::Prefix,
668 },
669 Binding {
670 keys: "} ] )",
671 desc: "closer on indent-only line dedents",
672 sections: &["insert"],
673 live: true,
674 id: "insert-closers",
675 handler: Handler::Prefix,
676 },
677 Binding {
679 keys: "space e",
680 desc: "reveal source in its Directory buffer",
681 sections: &["leader"],
682 live: true,
683 id: "directory-reveal",
684 handler: Handler::Leaf(|e, _| e.reveal_source()),
685 },
686 Binding {
687 keys: "space f",
688 desc: "file finder",
689 sections: &["leader"],
690 live: true,
691 id: "files",
692 handler: Handler::Leaf(|e, _| e.open_picker(strop_picker::Kind::Files)),
693 },
694 Binding {
695 keys: "space o",
696 desc: "open remote destination",
697 sections: &["leader"],
698 live: true,
699 id: "remote-open",
700 handler: Handler::Leaf(|e, _| e.open_remote_picker()),
701 },
702 Binding {
703 keys: "space b",
704 desc: "buffers (MRU)",
705 sections: &["leader"],
706 live: true,
707 id: "buffers",
708 handler: Handler::Leaf(|e, _| e.open_picker(strop_picker::Kind::Buffers)),
709 },
710 Binding {
711 keys: "space /",
712 desc: "Search workspace (resume investigation)",
713 sections: &["leader"],
714 live: true,
715 id: "search",
716 handler: Handler::Leaf(|e, _| e.open_search(false)),
717 },
718 Binding {
719 keys: "space R",
720 desc: "Search with replacement",
721 sections: &["leader"],
722 live: true,
723 id: "replace-global",
724 handler: Handler::Leaf(|e, _| e.open_search(true)),
725 },
726 Binding {
727 keys: "space ?",
728 desc: "help buffer",
729 sections: &["leader"],
730 live: true,
731 id: "help",
732 handler: Handler::Leaf(|e, _| crate::editor::Editor::open_help(e)),
733 },
734 Binding {
735 keys: "space y",
736 desc: "yank motion → system clipboard",
737 sections: &["leader"],
738 live: true,
739 id: "clip-yank",
740 handler: Handler::Leaf(|e, _| e.clipboard_yank_pub()),
741 },
742 Binding {
743 keys: "space p",
744 desc: "paste clipboard after",
745 sections: &["leader"],
746 live: true,
747 id: "clip-paste",
748 handler: Handler::Leaf(|e, k| e.clipboard_paste_pub(k == 'P')),
749 },
750 Binding {
751 keys: "space P",
752 desc: "paste clipboard before",
753 sections: &["leader"],
754 live: true,
755 id: "clip-paste-before",
756 handler: Handler::Leaf(|e, k| e.clipboard_paste_pub(k == 'P')),
757 },
758 Binding {
759 keys: "space d",
760 desc: "diagnostics picker",
761 sections: &["leader"],
762 live: true,
763 id: "diagnostics",
764 handler: Handler::Leaf(|e, _| e.open_diagnostics_picker()),
765 },
766 Binding {
767 keys: "space k",
768 desc: "hover docs",
769 sections: &["leader"],
770 live: true,
771 id: "hover",
772 handler: Handler::Leaf(|e, _| e.lsp_hover_pub()),
773 },
774 Binding {
775 keys: "space a",
776 desc: "context actions (code / filesystem)",
777 sections: &["leader"],
778 live: true,
779 id: "code-actions",
780 handler: Handler::Leaf(|e, _| e.context_actions()),
781 },
782 Binding {
783 keys: "space s",
784 desc: "document symbols picker",
785 sections: &["leader"],
786 live: true,
787 id: "document-symbols",
788 handler: Handler::Leaf(|e, _| e.lsp_document_symbols_pub()),
789 },
790 Binding {
791 keys: "space S",
792 desc: "workspace symbols picker",
793 sections: &["leader"],
794 live: false,
795 id: "workspace-symbols",
796 handler: Handler::Soon,
797 },
798 Binding {
799 keys: "space j",
800 desc: "jumplist picker",
801 sections: &["leader"],
802 live: true,
803 id: "jumplist-picker",
804 handler: Handler::Leaf(|e, _| e.open_picker(strop_picker::Kind::Jumps)),
805 },
806 Binding {
807 keys: "space u",
808 desc: "undo-tree browser",
809 sections: &["leader"],
810 live: true,
811 id: "undo-tree",
812 handler: Handler::Leaf(|e, _| crate::editor::Editor::open_undo_tree(e)),
813 },
814 Binding {
815 keys: "space c",
816 desc: "cursor on next line too (multicursor)",
817 sections: &["leader"],
818 live: true,
819 id: "cursor-stack",
820 handler: Handler::Leaf(|e, _| crate::editor::Editor::add_cursor_next_line(e)),
821 },
822 Binding {
824 keys: "space g",
825 desc: "git…",
826 sections: &["git"],
827 live: true,
828 id: "git-prefix",
829 handler: Handler::Prefix,
830 },
831 Binding {
832 keys: "space g l",
833 desc: "commit browser",
834 sections: &["git"],
835 live: true,
836 id: "git-log",
837 handler: Handler::Leaf(|e, _| e.open_log_pub(false)),
838 },
839 Binding {
840 keys: "space g h",
841 desc: "file history (visual: selected lines)",
842 sections: &["git"],
843 live: true,
844 id: "git-file-history",
845 handler: Handler::Leaf(|e, _| e.open_log_pub(true)),
846 },
847 Binding {
848 keys: "space g b",
849 desc: "toggle blame gutter / card",
850 sections: &["git"],
851 live: true,
852 id: "git-blame",
853 handler: Handler::Leaf(|e, _| e.toggle_blame_gutter()),
854 },
855 Binding {
856 keys: "space g y",
857 desc: "permalink: copy",
858 sections: &["git"],
859 live: true,
860 id: "git-permalink-yank",
861 handler: Handler::Leaf(|e, _| e.yank_permalink()),
862 },
863 Binding {
864 keys: "space g o",
865 desc: "permalink: open",
866 sections: &["git"],
867 live: true,
868 id: "git-permalink-open",
869 handler: Handler::Leaf(|e, _| e.open_permalink()),
870 },
871 Binding {
872 keys: "space g u",
873 desc: "hunk: undo unstaged (restore from index)",
874 sections: &["git"],
875 live: true,
876 id: "git-hunk-undo",
877 handler: Handler::Leaf(|e, _| e.undo_hunk()),
878 },
879 Binding {
880 keys: "space g s",
881 desc: "hunk: stage (live→index)",
882 sections: &["git"],
883 live: true,
884 id: "git-hunk-stage",
885 handler: Handler::Leaf(|e, _| e.stage_hunk()),
886 },
887 Binding {
888 keys: "space g S",
889 desc: "hunk: unstage (index→HEAD)",
890 sections: &["git"],
891 live: true,
892 id: "git-hunk-unstage",
893 handler: Handler::Leaf(|e, _| e.unstage_hunk()),
894 },
895 Binding {
896 keys: "space g p",
897 desc: "hunk: preview",
898 sections: &["git"],
899 live: true,
900 id: "git-hunk-preview",
901 handler: Handler::Leaf(|e, _| e.preview_hunk()),
902 },
903 Binding {
904 keys: "]f [f",
905 desc: "next / prev file in commit diff",
906 sections: &["git"],
907 live: true,
908 id: "commit-file-nav",
909 handler: Handler::Soon,
910 },
911 Binding {
912 keys: "enter",
913 desc: "dive into the line's commit (blame gutter)",
914 sections: &["git"],
915 live: true,
916 id: "surface-dive",
917 handler: Handler::Prefix,
918 },
919 Binding {
920 keys: "q",
921 desc: "close surface (readonly buffers)",
922 sections: &["git"],
923 live: true,
924 id: "surface-close",
925 handler: Handler::Prefix,
926 },
927 Binding {
929 keys: ":w :q :q! :wq :w {file} :trust",
930 desc: "write / quit (force) / write-quit / write-as",
931 sections: &["ex+panes"],
932 live: true,
933 id: "ex-write-quit",
934 handler: Handler::TextLine,
935 },
936 Binding {
937 keys: ":[range]s/a/b/[g] :N :% :N,Md :N,My",
938 desc: "substitute (literal) / goto line / ranged delete+yank",
939 sections: &["ex+panes"],
940 live: true,
941 id: "ex-ranges",
942 handler: Handler::TextLine,
943 },
944 Binding {
945 keys: "ctrl-d ctrl-u ctrl-f ctrl-b",
946 desc: "half/full page scroll (count = lines)",
947 sections: &["ex+panes"],
948 live: true,
949 id: "scroll-pages",
950 handler: Handler::TextLine,
951 },
952 Binding {
953 keys: ":e",
954 desc: "edit file",
955 sections: &["ex+panes"],
956 live: true,
957 id: "ex-edit",
958 handler: Handler::TextLine,
959 },
960 Binding {
961 keys: ":help",
962 desc: "help buffer (this text — / searches it)",
963 sections: &["ex+panes"],
964 live: true,
965 id: "ex-help",
966 handler: Handler::TextLine,
967 },
968 Binding {
969 keys: ":vs :sp",
970 desc: "split vertical / horizontal",
971 sections: &["ex+panes"],
972 live: true,
973 id: "ex-split",
974 handler: Handler::TextLine,
975 },
976 Binding {
977 keys: "ctrl-w h / l / j / k / w",
978 desc: "pane move / cycle",
979 sections: &["ex+panes"],
980 live: true,
981 id: "pane-nav",
982 handler: Handler::Leaf(crate::editor::Editor::pane_move_pub),
983 },
984 Binding {
985 keys: "ctrl-o / ctrl-i (tab)",
986 desc: "jump back / forward (jumplist)",
987 sections: &["ex+panes"],
988 live: true,
989 id: "jumplist",
990 handler: Handler::Leaf(|e, _| crate::editor::Editor::jump_back(e)),
991 },
992 Binding {
993 keys: "ctrl-w v / s",
994 desc: "pane split (vs / sp)",
995 sections: &["ex+panes"],
996 live: true,
997 id: "pane-split",
998 handler: Handler::Leaf(crate::editor::Editor::split_pub),
999 },
1000 Binding {
1001 keys: ":view :set",
1002 desc: "readonly browsing (:set ro/noro; CLI: -R)",
1003 sections: &["ex+panes"],
1004 live: true,
1005 id: "readonly",
1006 handler: Handler::TextLine,
1007 },
1008 Binding {
1009 keys: "ctrl-w q",
1010 desc: "close pane (last → buffer)",
1011 sections: &["ex+panes"],
1012 live: true,
1013 id: "pane-close",
1014 handler: Handler::Leaf(|e, _| crate::editor::Editor::pane_close_pub(e)),
1015 },
1016 Binding {
1017 keys: "up down left right tab s-tab",
1018 desc: "picker navigation / arrows = hjkl everywhere",
1019 sections: &["ex+panes"],
1020 live: true,
1021 id: "picker-nav",
1022 handler: Handler::Prefix,
1023 },
1024 Binding {
1025 keys: "ctrl-x",
1026 desc: "Search: exclude/include match",
1027 sections: &["ex+panes"],
1028 live: true,
1029 id: "search-exclude",
1030 handler: Handler::Contextual,
1031 },
1032 Binding {
1033 keys: "ctrl-space",
1034 desc: "query field: qualifier, language and value suggestions",
1035 sections: &["ex+panes"],
1036 live: true,
1037 id: "query-suggestions",
1038 handler: Handler::Contextual,
1039 },
1040 Binding {
1041 keys: "ctrl-d",
1042 desc: "Search: exclude/include file",
1043 sections: &["ex+panes"],
1044 live: true,
1045 id: "search-file-exclude",
1046 handler: Handler::Contextual,
1047 },
1048 Binding {
1049 keys: "ctrl-r",
1050 desc: "Search: toggle replacement; document: redo",
1051 sections: &["ex+panes"],
1052 live: true,
1053 id: "search-replacement",
1054 handler: Handler::Contextual,
1055 },
1056 Binding {
1057 keys: "enter",
1058 desc: "Search Find: open source; With: prepare review",
1059 sections: &["ex+panes"],
1060 live: true,
1061 id: "search-accept",
1062 handler: Handler::Contextual,
1063 },
1064 Binding {
1065 keys: "ctrl-o",
1066 desc: "Search: collect included matches",
1067 sections: &["ex+panes"],
1068 live: true,
1069 id: "search-collect",
1070 handler: Handler::Contextual,
1071 },
1072 Binding {
1073 keys: ":tab-size :indent-style :search-options",
1074 desc: "source indentation and search visibility controls",
1075 sections: &["ex+panes"],
1076 live: true,
1077 id: "source-and-search-settings",
1078 handler: Handler::Contextual,
1079 },
1080 Binding {
1081 keys: ":fs :browse :filter",
1082 desc: "filesystem actions, namespace-aware browsing and folder filtering",
1083 sections: &["ex+panes"],
1084 live: true,
1085 id: "filesystem",
1086 handler: Handler::Contextual,
1087 },
1088 Binding {
1089 keys: ":apply-change :cancel-change :save-change",
1090 desc: "review: apply text or filesystem changes, cancel, or save changed text",
1091 sections: &["ex+panes"],
1092 live: true,
1093 id: "change-review-actions",
1094 handler: Handler::Contextual,
1095 },
1096 Binding {
1097 keys: "ctrl-l",
1098 desc: "redraw: full repaint when the terminal desyncs",
1099 sections: &["ex+panes"],
1100 live: true,
1101 id: "redraw",
1102 handler: Handler::Leaf(|e, _| e.needs_repaint = true),
1103 },
1104];
1105
1106pub(crate) mod lookup;
1107
1108pub use lookup::{any_child, children_of, compat_report, find_row, Hint};
1109
1110#[cfg(test)]
1111mod tests;