update: thanks to @djblue we are close to supporting all of the emmy viewers in portal, like this: this one should be dragging the plot around, and it will, soon! EDIT: it works great:
it should look like this:
Can't get the inequality bit working, probably have the wrong version of the code, but the atoms are working for this example if you wrap the code in an fn
Also default viewers can be specified at all levels so this viewer will compose will all the other viewers in portal clojure-spin
For example:
(->
[:<>
[:portal.viewer/code "(+ 1 2 3)"]
[:portal-present.viewer/mafs
'(fn []
(reagent.core/with-let
[G__68160 (reagent.core/atom [0 0])]
[:<>
[:pre (clojure.core/pr-str @G__68160)]
[mafs.core/Mafs
[mafs.coordinates/Cartesian {}]
(reagent.core/with-let
[G__68161
(js/Function.
"[y0001]"
"[p0002]"
" const _0006 = - p0002;\n const _0008 = _0006 + y0001;\n const _0013 = Math.sinh(_0008);\n const _0014 = Math.cosh(_0008);\n const _0015 = Math.pow(_0014, 4.0);\n return (- 6.0 * Math.pow(_0013, 4.0) + 8.0 * Math.pow(_0013, 2.0) * Math.pow(_0014, 2.0) - 2.0 * _0015) / _0015;")]
[mafs.plot/OfX
{:y
(let [G__68162 (mapv @G__68160 [0])] (fn [x] (G__68161 [x] G__68162)))}])
(reagent.core/with-let
[G__68163
(js/Function.
"[y0001]"
"[p0002]"
" const _0006 = - p0002;\n const _0008 = _0006 + y0001;\n const _0013 = Math.sinh(_0008);\n const _0014 = Math.cosh(_0008);\n const _0015 = Math.pow(_0014, 4.0);\n return (- 6.0 * Math.pow(_0013, 4.0) + 8.0 * Math.pow(_0013, 2.0) * Math.pow(_0014, 2.0) - 2.0 * _0015) / _0015;")
G__68165
(js/Function. "y0001" " return Math.cos(y0001);")]
#_[mafs.plot/Inequality
{:y
{:<=
(let [G__68164 (mapv @G__68160 [0])] (fn [x] (G__68163 [x] G__68164))),
:> G__68165},
:color :blue}])
[mafs.core/MovablePoint {:atom G__68160, :constrain "horizontal"}]]]))]]
(with-meta {:portal.viewer/default :portal.viewer/hiccup}))In terms of downstream users resolving npm deps, not sure how you envisioned it, but the following might be a start:
In jvm land
(try
(portal.api/eval-str "(js/require \"mafs\")")
(catch Exception e <install deps for user or ask them to do so>))If you wanted to vendor your npm deps, portal can resolve js files from the classpath ๐
@djblue I do specify deps.cljs , could we pull them from there?
@djblue in clerk I have been building a custom JS bundle that includes everything, but this approach seems obviously easier to extend
(ev/with-let [!phase [0 0]]
(let [shifted (ev/with-params {:atom !phase :params [0]}
(fn [shift]
(((cube D) tanh) (- identity shift))))]
[:<>
[:pre `(pr-str @~!phase)]
(mafs/mafs
(mafs/cartesian)
(mafs/of-x shifted)
(mafs/inequality
{:y {:<= shifted :> cos} :color :blue})
(mafs/movable-point
{:atom !phase :constrain "horizontal"}))]))the fn trick worked great:
(p/register-viewer!
{:name ::mafs
:predicate (constantly true)
:component (fn [form]
(eval (list 'fn [] form)))})Currently Portal doesn't look for deps.cljs, it could but I'm not sure how that would play with how shadow treats it
If you already have the code vendor'd:
;; in cljs land
(def mafs
(try
(js/require "./vendor.js")
(catch :default e (js/reauire "mafs"))))
Or perhaps fallback to the vendor if the npm version isn't available
What are your expectations for the deps.cljs file?
my expectation was that any consumer of mafs.cljs will build a bundle with shadow, and that this file would trigger shadow into running npm install mafs with the correct version;
https://github.com/mentat-collective/Mafs.cljs/blob/main/src/deps.cljs
and save the user from having to do it manually
same with mathbox.cljs, leva.cljs etc
Interesting, so with Portal you get the convenience of no bundles but the inconvenience of resolving npm deps ๐
(clicking to interact seems to also โbegin filteringโ always, not sure if that matters enough to figure out a way around! doesnโt seem to impact the animation at all)
Interesting, might need to stop some events from propagating ๐ค
Not sure if you are interested, but you have access to portal.ui.theme, which will automatically work with editor based themes
Also, would getting this working in calva notebooks be something you want? https://cljdoc.org/d/djblue/portal/0.40.0/doc/editors/vs-code/clojure-notebooks
yes, absolutely
that looks very powerful, and absolutely fits in with my goals here, of having these viewers come to the user wherever they are
It looks like it should be able to work as long as people have the portal.nrepl/wrap-notebook nrepl middleware setup ๐ฅ
And some slight tweaks that I'm about to merge ๐
https://github.com/djblue/portal/releases/tag/0.41.0 has all the changes so far to get things working ๐
Also, not sure if this is important to you but Portal also works for the #clr and it looks like emmy is a lot of cljc ๐ค
Tell me about this portal.nrepl/wrap-notebook middleware?!?
By default, calva notebooks pass along edn from nrepl to the portal viewer so all the rich runtime data is gone (no datafy/nav, etc...). With this middleware, portal can detect if you are in a notebook, intercept the runtime value and pass along an id, then in the notebook viewer it can hookup portal to your runtime and everything works as a normal runtime connected portal.
The following bits are enabled with the middleware: โข https://cljdoc.org/d/djblue/portal/0.40.0/doc/datafy-nav โข First class object support โข Runtime registered commands โข Larger values which are harder for edn to serialize and parse โข Better error rendering
I think once calva notebooks support clojure-lsp, they are gonna be a top tier development environment
I may have done a thing ๐
(def ^:private theme-mapping
{:fg ::c/text
:bg ::background
:line-color ::c/border
:red ::c/exception
:orange ::c/uri
:green ::c/string
:blue ::c/namespace
:indigo ::c/boolean
:violet ::c/package
:pink ::c/number
:yellow ::c/tag})
(defn- ->style [theme]
(str
".MafsView {"
(str/join
";"
(reduce-kv
(fn [out mafs portal]
(conj out (str "--mafs-" (name mafs) ": " (get theme portal))))
[]
theme-mapping))
"}"))I really love this
Added the wrap-notebook middleware and I'm trying out the Clojure Notebook thing... very cool! Seems it selects Portal rendering by default? (good)
One downside seems to be that if you have RCFs -- (comment ...) blocks -- in your file and you tell the Notebook to "Run All", it evaluates the contents of those RCFs as well as all the top-level forms... which is kinda dangerous (given some of the code I have in RCFs!). It doesn't look like there's even a way to visually distinguish regular top-level forms from the contents of RCFs?
Is the Notebook format just fundamentally incompatible with the RCF-based approach?
(and is there a better channel to ask about this?)
The Calva integration was mostly handled by @domagala.lukas so he probably knows more about the details / limitations
I think the #calva channel might be a good place to have this convo but I'm also cool if we continue it here ๐
Cool, thanks. I remember seeing some discussions about it but couldn't remember where...
I feel like https://github.com/BetterThanTomorrow/calva/blob/published/src/NotebookProvider.ts#L171-L173 could be updated to ignore forms from comments ๐ค
I think when the parser splits apart the comment form into multiple cells, it might be able to mark them as special to filter them out in this for loop. Then, the only method of evaluation would be eval'ing the cell alone.
I'm not at home right now so I can't link to it but there should be a github discussion on this in the calva repo
https://github.com/BetterThanTomorrow/calva/discussions/1825 -- Thanks, @domagala.lukas!
The parser already marks comment forms as special, so we can do the filtering. Iโll go ahead and do it, @domagala.lukas. Holler if you see a reason not to do this.
Having refreshed my memory -- since I participated quite a bit in that thread -- it seems that the restrictions with RCFs are known about but unsolved, which certainly makes it dangerous for me to use at present ๐ Issue 2210 needs to also skip RCFs in the run cells above and run cell & below commands. I'll add that note to the issue.
This VSIX should fix it https://output.circle-artifacts.com/output/job/7f57b12b-206f-444d-bbea-b622700cd2b4/artifacts/0/tmp/artifacts/calva-2.0.365-2210-rich-comment-notebook-run-all-9710d2c3.vsix Do you have time to test it, @seancorfield? Otherwise, Iโll just release it and we can fix any remaining issues later. The run cells above and below cases should be covered the way I did the filtering.
Sure, I can try it...
@djblue found a bug. ๐ New VSIX building.
The bug was that evaluation of cells below a comment cell would not happen either. Now they do (unless they are comment cells).
I installed that but there still seems to be a bug in Cell and Below...
Can you describe? It seems to work when I try it.
Trying to repro...
Ah, my bad, I had a defn- inside a long RCF and couldn't tell in notebook view -- and it wasn't getting evaluated, but when I scrolled down I found real top-level forms were evaluated! So it does seem correct. Thank you!
I wish there was a way to visually tell that a cell is part of an RCF ๐
Yeah, that would be nice. Dunno how possible.
And ;; line comments don't appear in notebook cells (which would have clued me into this being in an RCF).
It's got a ways to go... but it's certainly a lot safer to use now! ๐
Calvaโs feature for creating an RCF tucks an :rcf at the closing bracket. Thatโs retained as a cell in the notebook.
Hmm, I don't see that:
I wonder if comment cells can be styled with a border or something ๐ค
Oh, @pez You mean some specific feature in Calva that inserts an RCF actually inserts this?
(comment
:rcf)
I have never used that (since it's so easy to just type (comm and tab-complete to accept the RCF suggestion)!Yeah, itโs a bit of a silly feature. More for people to discover RCFs as such. But it does work well if youโre inside some function and want to create (or jump to) an RCF below it.
For notebooks, it looks like https://github.com/microsoft/vscode/blob/main/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts#L227https://github.com/microsoft/vscode/blob/main/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts#L227 and I'm not seeing an official way to customize some of the styling ๐ค
Yeah Iโd love to style them somehow. The best Iโve come up with is to show the (comment and ) as cells but that seems weird as well ๐
And thanks @pez for quickly implementing this. At some point, we might want to make run-all for RCF optional but off by default seems like a good safety feature.