Fix defcomp to detect components in HSX

This commit is contained in:
Akira Tempaku 2024-12-13 01:33:01 +09:00
commit dfc074ec71
2 changed files with 42 additions and 31 deletions

View file

@ -13,27 +13,34 @@
;;;; hsx macro
(defmacro hsx (form)
"Detect built-in HSX elements and automatically import them."
(find-builtin-symbols form))
"Detect HSX elements and automatically import them."
(detect-elements form))
(defun get-builtin-symbol (sym)
(multiple-value-bind (builtin-sym kind)
(find-symbol (string sym) :hsx/builtin)
(and (eq kind :external) builtin-sym)))
(defun find-builtin-symbols (form)
(defun start-with-tilde-p (sym)
(string= "~" (subseq (string sym) 0 1)))
(defun get-component-symbol (sym)
(and (start-with-tilde-p sym) sym))
(defun detect-elements (form)
(check-type form cons)
(let* ((head (first form))
(tail (rest form))
(well-formed-p (listp tail))
(builtin-sym (and (symbolp head)
(not (keywordp head))
(get-builtin-symbol head))))
(if (and well-formed-p builtin-sym)
(cons builtin-sym
(detected-sym (and (symbolp head)
(not (keywordp head))
(or (get-builtin-symbol head)
(get-component-symbol head)))))
(if (and well-formed-p detected-sym)
(cons detected-sym
(mapcar (lambda (sub-form)
(if (consp sub-form)
(find-builtin-symbols sub-form)
(detect-elements sub-form)
sub-form))
tail))
form)))
@ -67,16 +74,19 @@
`(eval-when (:compile-toplevel :load-toplevel :execute)
(defhsx ,name ,(make-keyword name))))
(defmacro defcomp (name props &body body)
"Define a function component for use in HSX.
The props must be declared with either &key or &rest (or both).
(defmacro defcomp (~name props &body body)
"Define a function component for HSX.
The component name must start with a tilde (~).
Properties must be declared using &key, &rest, or both.
The body must return an HSX element."
(unless (start-with-tilde-p ~name)
(error "The component name must start with a tilde (~~)."))
(unless (or (null props)
(member '&key props)
(member '&rest props))
(error "Component properties must be declared with either &key, &rest, or both."))
(let ((%name (symbolicate '% name)))
(let ((%name (symbolicate '% ~name)))
`(eval-when (:compile-toplevel :load-toplevel :execute)
(defun ,%name ,props
,@body)
(defhsx ,name (fdefinition ',%name)))))
(defhsx ,~name (fdefinition ',%name)))))