hey! I'm unsure on how to integrate expound in a cljs project: I added [expound "0.8.7"]
to my shadow-cljs.edn
, and then I changed the init!
function to:
(defn ^:export init! []
(set! s/*explain-out* expound/printer)
(mount-root))
that said, when a spec fails, I still get the usual error in the emacs minibuffer. No expound
magic! Can you help me?@meditans Is it possible to test this without emacs? Does this reproduce if you just call the function in a shadow-cljs REPL on the command line?
(I haven’t used shadow-cljs, so I’m not familiar with the tooling)
ok, so, the library works if I do something like (expound/expound string? 1)
What if you instrument a function and then call it with invalid parameters?
it prints the output that I would expect; it's just that I don't know what to do to make my program aware
(In the command-line REPL)
let's see
In particular, CIDER can do several things with errors - it can print them to the REPL in emacs, or it can open up a CIDER specific error buffer. It should be possible to see Expound errors in the former, but I don’t know how to adjust the latter.
That’s because the code in your REPL doesn’t impact how CIDER prints spec errors - that’s specific to CIDER itself, which doesn’t know about expound
give me a couple of minutes, I'm still learning clojure and I'm unsure on how to do a couple of things; googling
No rush. My reason I’m asking these questions
1. A command-line REPL is simplest. This will prove we are actually getting everything set up correct e.g. init!
is being called as expected
2. If that works, we can then connect to a REPL in CIDER and try typing everything out in REPL, see if that works
3. Finally we can try evaluating commands in CIDER within the actual code buffer, and see what happens.
ok here's what I did:
(defn add1 [x] (+ 1 x))
(s/fdef add1 :args number?)
(stest/instrument `add1)
;; now (add1 nil) gives the normal error
(set! s/*explain-out* expound/printer)
;; (add1 nil) gives still the normal error
ok, that was done in a repl emacs opened for me. Is there a preferred way of calling a plain repl?
Where is the normal error printed? In the REPL buffer?
indeed
that buffer is called cider-repl clojure/...
Interesting! Here’s the same repro in a basic terminal REPL started with clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.773"} expound {:mvn/version "0.8.7"}}}' -e cljs.main -re node
(require '[clojure.spec.test.alpha :as stest])
(require '[clojure.spec.alpha :as s])
(require '[expound.alpha :as expound])
(defn add1 [x] (+ 1 x))
(s/fdef add1 :args number?)
(stest/instrument `add1)
(set! s/*explain-out* expound/printer)
(add1 nil)
thank you let me try that
That prints:
Execution error - invalid arguments to cljs.user/add1 at (<cljs repl>:1).
<filename missing>:<line number missing>
-- Spec failed --------------------
Function arguments
(nil)
should satisfy
number?
-------------------------
Detected 1 error
which leads me to believe the next step is trying to figure out a CLJS REPL in shadow and see if it’s different (my REPL above is not managed by shadow, just so we can compare)
hmm here's what I get:
clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.773"} expound {:mvn/version "0.8.7"}}}' -e cljs.main -re node
DEPRECATED: Libs must be qualified, change expound => expound/expound
WARNING: When invoking clojure.main, use -M
Syntax error (ClassNotFoundException) compiling at (REPL:0:0).
cljs.main
Full report at:
/tmp/clojure-485995736718039585.edn
ah, sorry, my CLJ is probably a bit old.
clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.773"} expound/expound {:mvn/version "0.8.7"}}}' -e cljs.main -re node
does that work?
no, but a somehow smaller message:
WARNING: When invoking clojure.main, use -M
Syntax error (ClassNotFoundException) compiling at (REPL:0:0).
cljs.main
Full report at:
/tmp/clojure-3622056146492718952.edn
so no deprecation, and no warning
Well shoot. Let me upgrade my version of clj
clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.773"} expound {:mvn/version "0.8.7"}}}' -M -m cljs.main -re node
might work, but upgrading is taking a second
yeah, that works
is the only difference expound
vs expound/expound
?
and I added “-M”
I see, to "supply main opts" I imagine
let me complete the test
yes that prints everything in the format expected by expound
ClojureScript 1.10.773
cljs.user=> (require '[clojure.spec.test.alpha :as stest])
nil
cljs.user=> (require '[clojure.spec.alpha :as s])
nil
cljs.user=> (require '[expound.alpha :as expound])
nil
cljs.user=> (defn add1 [x] (+ 1 x))
#'cljs.user/add1
cljs.user=> (s/fdef add1 :args number?)
cljs.user/add1
cljs.user=> (stest/instrument `add1)
[cljs.user/add1]
cljs.user=> (set! s/*explain-out* expound/printer)
#object[expound$alpha$printer]
cljs.user=> (add1 nil)
Execution error - invalid arguments to cljs.user/add1 at (<cljs repl>:1).
<filename missing>:<line number missing>
-- Spec failed --------------------
Function arguments
(nil)
should satisfy
number?
-------------------------
Detected 1 error
Hm, so I think the next question is “does it work with shadow-cljs without emacs?”
which means, how do I open a shadow repl? Let me try googling
It looks like shadow can start a REPL with shadow-cljs cljs-repl app
or shadow-cljs node-repl
but I’m going to need to install Shadow to check
https://shadow-cljs.github.io/docs/UsersGuide.html#_command_line
I don't seem to have shadow-cljs
globally installed, let's see
Hm, me either. And it’s not clear to me how shadow-cljs
will pick up dependencies in that case. Maybe that’s a bad idea
Are you using deps.edn
or lein
for your project?
probably because I created a template using lein
so to create the template I used lein, but my deps are in a file called shadow-cljs.edn
ah, gotcha
Ah, OK, that makes sense. I will make a shadow-cljs.edn
file now
here's the command I used to create the project if it helps lein new reagent-frontend my-example +shadow-cljs
OK, here’s what I did
yarn shadow-cljs node-repl
(and expound is in my dependencies in shadow-cljs.edn
)
then I ran the sequence above and I did not get the expound output
interesting! Let me try, just for good measure, although I'm sure I won't get that either
but anyway, why would that happen?
In fact, it looks like shadow is printing the raw error object
#error {:message "Call to #'cljs.user/add1 did not conform to spec.", :data {:cljs.spec.alpha/problems [{:path [], :pred cljs.core/number?, :val (nil), :via [], :in []}], :cljs.spec.alpha/spec #object[cljs.spec.alpha.t_cljs$spec$alpha30168], :cljs.spec.alpha/value (nil), :cljs.spec.alpha/fn cljs.user/add1, :cljs.spec.alpha/args (nil), :cljs.spec.alpha/failure :instrument}}
the one that begins with #error
exactly
yeah, that's what gets printed in emacs also
Ah, cool, this is helpful. So that’s not even the old error message - note that is different from what you get without shadow
that would be Execution error - invalid arguments to cljs.user/add1 at (<cljs repl>:1).
?
Note that if you modify my other REPL (without expound) and you don’t call (set! s/*explain-out* expound/printer)
, you get the following
Execution error - invalid arguments to cljs.user/add1 at (<cljs repl>:1).
(nil) - failed: number?
ha, yep, what you said 🙂
so anyway, my guess is that Shadow has it’s REPL configured to handle errors differently
I’m googling now on how to adjust it
awesome 🙂
Hm, I’m coming up empty so far. Basically if shadow lets you configure the REPL, we want to take that #error
object and send the data to expound
I'm also googling, let's see what we can find; maybe it would be worthwhile to just ask in #shadow-cljs?
https://shadow-cljs.github.io/docs/UsersGuide.html#_repl_3 maybe
Yeah, I think maybe #shadow-cljs would know more. I’m super new to shadow
:repl-pprint
?
do you want me to ask or do you want to do that yourself? (I have the feeling you understand better what this is about)
Feel free to ask - I unfortunately need to leave in a few minutes
But the general idea is that you want to turn that error into a string by calling expound/printer
with the data. You can get inspiration from what CLJS does on the REPL:
https://github.com/clojure/clojurescript/blob/5e88d3383e0f950c4de410d3d6ee11769f3714f4/src/main/cljs/cljs/repl.cljs#L218-L222
I'll do, thank you for all the help! 🙂
Good luck!
If you figure it out, let me know here or in Github and I’ll add a section to the readme for Shadow
I will, thanks!
no progress yet, but I opened an issue here https://github.com/thheller/shadow-cljs/issues/825