diff options
| -rw-r--r-- | modules/keybindings.el | 26 | ||||
| -rw-r--r-- | tests/test-init-keymap-registration.el | 45 | ||||
| -rw-r--r-- | todo.org | 2 |
3 files changed, 72 insertions, 1 deletions
diff --git a/modules/keybindings.el b/modules/keybindings.el index 6e8adeac..db480087 100644 --- a/modules/keybindings.el +++ b/modules/keybindings.el @@ -36,6 +36,32 @@ :doc "User custom prefix keymap base for nested keymaps.") (keymap-global-set "C-;" cj/custom-keymap) +;; ------------------------ Custom Keymap Registration ------------------------- + +;; Feature modules register into the C-; prefix through these helpers rather +;; than mutating `cj/custom-keymap' directly. This keeps keybindings.el the +;; sole owner of the prefix and removes each module's hidden assumption that +;; the keymap already exists. KEY is a `keymap-set'-style key relative to the +;; C-; prefix (e.g. "c" binds C-; c). Modules must (require 'keybindings). + +(defun cj/register-prefix-map (key map &optional label) + "Bind prefix keymap MAP under KEY within `cj/custom-keymap'. +When LABEL is non-nil, register it as the which-key description for the +\"C-; KEY\" prefix once which-key loads." + (keymap-set cj/custom-keymap key map) + (when label + (with-eval-after-load 'which-key + (which-key-add-key-based-replacements (concat "C-; " key) label)))) + +(defun cj/register-command (key command &optional label) + "Bind COMMAND under KEY within `cj/custom-keymap'. +When LABEL is non-nil, register it as the which-key description for the +\"C-; KEY\" key once which-key loads." + (keymap-set cj/custom-keymap key command) + (when label + (with-eval-after-load 'which-key + (which-key-add-key-based-replacements (concat "C-; " key) label)))) + ;; ------------------------------ Jump To Commands ----------------------------- (defun cj/jump-open-var (var) diff --git a/tests/test-init-keymap-registration.el b/tests/test-init-keymap-registration.el new file mode 100644 index 00000000..fcce1edb --- /dev/null +++ b/tests/test-init-keymap-registration.el @@ -0,0 +1,45 @@ +;;; test-init-keymap-registration.el --- Keymap registration API contract -*- lexical-binding: t; -*- + +;;; Commentary: +;; Phase 3 of the load-graph project introduces a small registration API in +;; keybindings.el so feature modules stop mutating `cj/custom-keymap' directly. +;; These tests pin the contract: a registered prefix map or command resolves +;; from `cj/custom-keymap', the which-key label is optional, and an invalid key +;; signals. Each test rebinds `cj/custom-keymap' to a fresh keymap so the real +;; global prefix is never polluted. + +;;; Code: + +(require 'ert) +(require 'cl-lib) + +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(require 'keybindings) + +(ert-deftest test-init-keymap-registration-prefix-map-resolves () + "Normal: a prefix map registered under KEY resolves from cj/custom-keymap." + (let ((cj/custom-keymap (make-sparse-keymap)) + (sub (make-sparse-keymap))) + (cj/register-prefix-map "a" sub "alpha") + (should (eq sub (keymap-lookup cj/custom-keymap "a"))))) + +(ert-deftest test-init-keymap-registration-command-resolves () + "Normal: a command registered under KEY resolves from cj/custom-keymap." + (let ((cj/custom-keymap (make-sparse-keymap))) + (cj/register-command "b" #'ignore "beta") + (should (eq #'ignore (keymap-lookup cj/custom-keymap "b"))))) + +(ert-deftest test-init-keymap-registration-label-optional () + "Boundary: registration without a LABEL still binds the key." + (let ((cj/custom-keymap (make-sparse-keymap)) + (sub (make-sparse-keymap))) + (cj/register-prefix-map "c" sub) + (should (eq sub (keymap-lookup cj/custom-keymap "c"))))) + +(ert-deftest test-init-keymap-registration-invalid-key-signals () + "Error: a non-string key is rejected by the underlying keymap-set." + (let ((cj/custom-keymap (make-sparse-keymap))) + (should-error (cj/register-prefix-map 42 (make-sparse-keymap))))) + +(provide 'test-init-keymap-registration) +;;; test-init-keymap-registration.el ends here @@ -412,7 +412,7 @@ Do this incrementally. After each batch: - Run =make test= or at least targeted tests. - Check that keybindings still resolve and which-key labels still appear. -**** TODO [#B] Centralize custom keymap registration :refactor: +**** DOING [#B] Centralize custom keymap registration :refactor: Many modules mutate =cj/custom-keymap= or global keys at top level. This is a real architectural boundary because it forces load order and makes standalone |
