branch: externals/keymap-popup
commit 72e406033618b49571ab2895bf183ce23aa7b21f
Author: Thanos Apollo <[email protected]>
Commit: Thanos Apollo <[email protected]>
macro: Declare keymap variables early
---
keymap-popup.el | 14 +++++++++
tests/keymap-popup-tests.el | 73 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/keymap-popup.el b/keymap-popup.el
index af38ec0a6f..412ec74fab 100644
--- a/keymap-popup.el
+++ b/keymap-popup.el
@@ -461,6 +461,19 @@ calls so lambdas in :if/:inapt-if/:description get
compiled."
(interactive)
(keymap-popup ,map-name)))
+(defun keymap-popup--build-declaration-forms (map-name parent entries)
+ "Build bare `defvar' forms for MAP-NAME, PARENT, and targets in ENTRIES."
+ (mapcar (lambda (symbol) `(defvar ,symbol))
+ (seq-uniq
+ (append (list map-name)
+ (and parent (symbolp parent) (list parent))
+ (cl-loop for entry in entries
+ for target = (plist-get entry :target)
+ when (and (eq (plist-get entry :type) 'keymap)
+ target
+ (symbolp target))
+ collect target)))))
+
(defun keymap-popup--build-meta-forms (map-name exit-key description
persistent)
"Build trailing `setf' forms for MAP-NAME's popup metadata.
Each of EXIT-KEY, DESCRIPTION, PERSISTENT is included only when non-nil."
@@ -524,6 +537,7 @@ pairs."
(keymap-pairs (keymap-popup--build-keymap-pairs name
all-entries))
(launcher (keymap-popup--launcher-name name)))
`(progn
+ ,@(keymap-popup--build-declaration-forms name parent all-entries)
,@(keymap-popup--build-switch-forms name switch-entries)
,@(keymap-popup--build-enter-forms name keymap-entries)
,(keymap-popup--build-launcher-form name launcher)
diff --git a/tests/keymap-popup-tests.el b/tests/keymap-popup-tests.el
index e51593b5c9..2431101697 100644
--- a/tests/keymap-popup-tests.el
+++ b/tests/keymap-popup-tests.el
@@ -87,6 +87,42 @@
;;; Macro tests
+(ert-deftest keymap-popup-test-macro-declarations-filter-keymap-expressions ()
+ (let* ((forms (cdr (macroexpand-1
+ '(keymap-popup-define keymap-popup--test-root-map
+ :parent (make-sparse-keymap)
+ "a" ("A" :keymap keymap-popup--test-sub-map)
+ "b" ("B" :keymap keymap-popup--test-sub-map)
+ "c" ("C" :keymap (make-sparse-keymap))))))
+ (declarations (seq-filter
+ (lambda (form) (eq (car-safe form) 'defvar))
+ forms)))
+ (should (equal declarations
+ '((defvar keymap-popup--test-root-map)
+ (defvar keymap-popup--test-sub-map))))))
+
+(ert-deftest keymap-popup-test-macro-declarations-omit-nil-parent ()
+ (let* ((forms (cdr (macroexpand-1
+ '(keymap-popup-define keymap-popup--test-no-parent-map
+ "r" ("Refresh" ignore)))))
+ (declarations (seq-filter
+ (lambda (form) (eq (car-safe form) 'defvar))
+ forms)))
+ (should (equal declarations
+ '((defvar keymap-popup--test-no-parent-map))))))
+
+(ert-deftest keymap-popup-test-macro-declarations-include-parent ()
+ (let* ((forms (cdr (macroexpand-1
+ '(keymap-popup-define keymap-popup--test-child-map
+ :parent keymap-popup--test-parent-map
+ "s" ("Sub" :keymap keymap-popup--test-parent-map)))))
+ (declarations (seq-filter
+ (lambda (form) (eq (car-safe form) 'defvar))
+ forms)))
+ (should (equal declarations
+ '((defvar keymap-popup--test-child-map)
+ (defvar keymap-popup--test-parent-map))))))
+
(ert-deftest keymap-popup-test-macro-creates-keymap ()
(eval '(keymap-popup-define keymap-popup--test-map-1
"Test keymap."
@@ -122,6 +158,43 @@
(should (boundp 'keymap-popup--test-sw))
(should (fboundp 'keymap-popup--test-map-3--toggle-keymap-popup--test-sw)))
+(ert-deftest keymap-popup-test-macro-declares-maps-before-helpers ()
+ (let* ((forms (cdr (macroexpand-1
+ '(keymap-popup-define keymap-popup--test-declared-map
+ "Test."
+ :parent keymap-popup--test-declared-parent
+ "s" ("Sub" :keymap
keymap-popup--test-declared-sub)))))
+ (map-pos (cl-position '(defvar keymap-popup--test-declared-map)
+ forms :test #'equal))
+ (parent-pos (cl-position '(defvar keymap-popup--test-declared-parent)
+ forms :test #'equal))
+ (sub-pos (cl-position '(defvar keymap-popup--test-declared-sub)
+ forms :test #'equal))
+ (launcher-pos (cl-position-if
+ (lambda (form)
+ (and (eq (car-safe form) 'defun)
+ (eq (cadr form)
+ 'keymap-popup--test-declared-map-popup)))
+ forms))
+ (enter-pos (cl-position-if
+ (lambda (form)
+ (and (eq (car-safe form) 'defun)
+ (eq (cadr form)
+
'keymap-popup--test-declared-map--enter-keymap-popup--test-declared-sub)))
+ forms))
+ (keymap-pos (cl-position-if
+ (lambda (form) (eq (car-safe form) 'defvar-keymap))
+ forms)))
+ (should map-pos)
+ (should parent-pos)
+ (should sub-pos)
+ (should launcher-pos)
+ (should enter-pos)
+ (should keymap-pos)
+ (should (< map-pos launcher-pos))
+ (should (< sub-pos enter-pos))
+ (should (< parent-pos keymap-pos))))
+
(ert-deftest keymap-popup-test-macro-emits-launcher-defun ()
"`keymap-popup-define' emits a named `defun' for the popup launcher."
(eval '(keymap-popup-define keymap-popup--test-launcher