Does Cherry support the #html [:div "xxx"] syntax of squint? I'm getting Error: No reader function for tag html.
Apparently not yet... issue welcome
Can I use defclass from a macro?
(defmacro create-class [class-name] `(defclass ~class-name))
(create-class MyTestClass)
This never creates a class, but rather produces this code:
var create_class = (function (_AMPERSAND_form, _AMPERSAND_env, class_name) {
return cherry_core.sequence.call(null, cherry_core.seq.call(null, cherry_core.concat.call(null, cherry_core.list.call(null, cherry_core.symbol.call(null, "defclass")), cherry_core.list.call(null, class_name))));
});
create_class.call(null, MyTestClass);
Beyond the minimalistic example provided above, my use-case are web components which always have the same definition, all that changes is the render fn, so I'd like to reduce the boilerplate.No worries, take your time.
Thanks for the reminder. Other issues got in the way, sorry. Issue welcome.
I might have some time today, hopefully
I'm on it now
have it working, but need to improve/clean up a little
Thank you very much @borkdude 🙏 It's really appreciated.
released in 0.3.20
Thank you. I will check later today, I'm just waking up.
@borkdude oh this is the hiccup. Nice!!! Thank you 🙏
This thread was actually about the macros though. I haven't reported it as an issue (just made the repro you asked for, see above). Do you want me to create an issue with the repro link in it?
But I'm definitely going to use the #html literal, it was me who reported that as you know so I'm very happy about that.
I can confirm it works like a charm, yay!
Issue please
I'll check out the repro repository now, sorry I fixed the wrong issue :)
@jakub.stastny.pt_serv ok, now you should be able to write the macro as:
(ns macros)
(defmacro create-class [class-name & args]
`(cherry.core/defclass ~class-name ~@args))
with 0.3.22
Thank you @borkdude, will check it out shortly.
Btw, I wonder if you could have also solved this without a macro using extends or so
It'd be slightly more verbose I think, it'd be class, extends and then WebComponents.define or what's the thing that registers it.
By the way the log message shows squint now rather than cherry:
$ npx cherry compile src/lib/macros.cljs
[squint] Compiling CLJS file: src/lib/macros.cljslol, let me fix that
fixed on cherry main
@borkdude I'm having issues with this one actually. So I'm in the repro repository and I have this:
(ns my-footer
(:require-macros [foo.macros :refer [create-class]]))
The file src/foo/macros.cljs is there with (ns foo.macros definition. Yet it doesn't work.in the repro repository you only had [macros :refer ...] right?
or did you update the repro?
Let me check, I thought this is how it was but let me see.
You're right, but even there I'm getting the same issue.
npx cherry compile src/components/my-footer.cljs
[squint] Compiling CLJS file: src/components/my-footer.cljs
node:internal/process/promises:288
triggerUncaughtException(err, true /* fromPromise */);
^
Error: The "path" argument must be of type string or an instance of Buffer or URL. Received null
This happens on the require-macros line.Even if the macros file is empty (beyond ns declaration), it still fails. It looks like it cannot find the file at all.
lemme try again locally
you shouldn't add this to your macro namespace:
(:require [cherry.core :refer [defclass]])instead, write this:
(ns macros)
(defmacro create-class [class-name]
`(cherry.core/defclass ~class-name))note that the output will still fail due to the absence of a constructor in the defclass
this is why I changed it thusly: https://clojurians.slack.com/archives/C03QZH5PG6M/p1726235055178639?thread_ts=1724958336.280949&cid=C03QZH5PG6M
Right!
OK now it compiles, will try on the main project whether it works.
you can now also print from the cherry macros
which wasn't possible before
so if you want to inspect the macro expansion, you can print it before returning it
also js interop is possible, so js/console.log etc
Cool!
@borkdude some of the serialisation in macros is broken, it gives me this$.attachShadow([object Object]):
class MyFooter extends HTMLElement {
constructor() {
super();const self__ = this;
const this$ = this;
this$.attachShadow([object Object]) }
connectedCallback() {
const this$ = this;
const self__ = this;return render.call(null, this$.shadowRoot);
}};
customElements.define("my-footer", MyFooter);
The macro:
(defmacro component [class-name element-name render-fn]
`(do
(cherry.core/defclass ~class-name
(~'extends js/HTMLElement)
(~'constructor [~'this]
(~'super)
(.attachShadow ~'this #js {"mode" "open"}))
~'Object
(~'connectedCallback [~'this]
(~render-fn (.-shadowRoot ~'this))))
(js/customElements.define ~element-name ~class-name)))
I will see if I can come up with a workaround and once I'm more familiar with the issue, I will report it to GH issues.you need to quote this: js/HTMLElement
no sorry, it's already in syntax-quote
what does the macro-expansion look like. before posting an issue, let's just check first if there's nothing wrong here
This won't work: #js {"mode" "open"}
That's exactly the problematic line, yes.
you can't emit a JS object from a macro, probably best to write (js-obj "mode" "open")
OK now it all works. Cool!
got a little busy, won't be able to check this this weekend, hopefully next week
@borkdude Sorry to bother you about this, but is there any update? If it's on the back-burner now, let me know and I will create an issue from the repro so it gets done eventually. In the end I could use Squint for now (although I have to say I very much prefer Cherry).
You can't define macros in the same file as cherry code, they have to live in a separate file. Also you need to fully qualify the defclass symbol yourself since it's not a normal symbol that is available in clojure
similar as described here: https://github.com/squint-cljs/squint?tab=readme-ov-file#macros
squint.edn doesn't exist for cherry though, but the src folder is used by default I believe
Thank you.
so just put a src/foo/macros.cljs file in your project
then (:require-macros [foo.macros :as m]) or so
@borkdude Also you need to fully qualify the defclass symbol yourself since it's not a normal symbol that is available in clojure
This bit I'm not sure about. I had this:
;; src/macros.cljs
(ns macros (:require [cherry.core :refer [defclass]]))
(defmacro create-class [class-name]
`(defclass ~class-name))
Upon reading about the fully qualified symbol, I changed it to this:
;; src/macros.cljs
(ns macros)
(defmacro create-class [class-name]
`(cherry.core/defclass ~class-name))
But neither of these work (wouldn't compile with Error: Nothing specified to load).is it possible to make a repro of this? I'll take a look tomorrow
Sure.
Thanks. I'll do it later, will post an issue here.
@borkdude https://github.com/jakub-stastny/cherry-macro-repro
cool, I'll check tomorrow