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