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

Reply via email to