This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-29
Channels
- # announcements (1)
- # babashka (15)
- # beginners (37)
- # calva (94)
- # cider (3)
- # clj-kondo (17)
- # cljsrn (2)
- # clojure (45)
- # clojure-europe (39)
- # clojure-germany (1)
- # clojure-norway (2)
- # clojurescript (16)
- # component (18)
- # conjure (1)
- # cursive (13)
- # datalevin (3)
- # datomic (12)
- # docker (2)
- # duct (5)
- # eastwood (2)
- # emacs (4)
- # events (8)
- # fulcro (8)
- # inf-clojure (5)
- # kaocha (8)
- # lsp (24)
- # malli (11)
- # meander (3)
- # off-topic (19)
- # polylith (11)
- # remote-jobs (4)
- # sci (61)
- # shadow-cljs (9)
- # spacemacs (34)
- # sql (10)
- # tools-deps (27)
- # xtdb (10)
Does the joyride extension support this behavior? 1. (Start a REPL externally via the terminal) - wait for the nrepl port file to appear 2. Connect to the REPL and the shadow-cljs build 3. Show a pop up when everything is successful - and play a sound all with a single command, without having to use any menus etc?
Essentially I guess I'm asking for: 1. Access to the file system 2. Ability to execute commands from other extensions (calva, portal, etc)
The tricky part could be the menus. Calva uses some calva-internal* state to pre-select items in its menus. In e2e tests we use this and then execute the vscode command for submitting the menu. If you can get at that state, you should be able to do the same. Otherwise it would be a bit more brittle, you would step through the menus x times and then submit. With a combination of a tight Connect Sequence you can minimize the things you need to do from Joyride. You reach the filesystem in a remote and liveshare safe way via vscode/workspace.fs
(an idea for an example there, @U04V15CAJ).
• The terminal example should show you how to do the launching part
• I've never played sounds in a vscode extension, but I'm pretty sure it should be possible, otherwise shell out for this maybe
*At least I think it is internal, the Memento instance is actually called globalState
https://code.visualstudio.com/api/extension-capabilities/common-capabilities#data-storage.
@U7PBP4UVA 1 is certainly possible. see the examples directory, there is a terminal.cljs
file in there
2. @U0ETXRFEW maybe Calva could export an extension function for this or so?
> 2. @U0ETXRFEW maybe Calva could export an extension function for this or so? Not sure what "this” is, but Calva should and will expose a nice API. Will just take some time to design. To not block on that, I'd do it the way I did in my ignore-form-example. Just bang on the commands. 😃
My end goal is to be able to start a prepared environment with calva, portal etc - for a specific project or work session. Seems like it's doable! I'll have a play next week. Awesome idea with joyride!

The “play sound” is possible? :shocked_face_with_exploding_head:
Is there a way to change the keyboard shortcut for evaluating in the repl window? Here’s the behavior I see (`|` is the cursor):
(+ 1 1|)
<enter>
(+ 1 1
|)
(+ 1 1)|
<enter>
=> 2
(+ 1 1|)
<alt+enter>
=> 2
What I’d like to change it to is this:
(+ 1 1|)
<enter>
(+ 1 1
) ;; The same
(+ 1 1)|
<enter>
(+ 1 1)
|
(+ 1 1|)
<alt+enter>
=>2
This is especially annoying when the editor suggestions popup is active, since I use “enter” to select suggestions. In the output window, calva instead skips picking the selected suggestion and just evaluates whatever I’ve typedThe annoying thing is rather a bug. You could add something like !suggestWidgetVisible
to the when
clause of the keybinding to stop that. (And please file an issue on Calva to it in the default config.)
Actually, that's already there... I don't understand why it doesn't work. Maybe it is some other widgetVisible we need to exclude...
The other behaviour is intended. If the cursor is behind the top level form enter
submits. Otherwise inserts an enter.
It's defined like so:
{
"command": "calva.evaluateOutputWindowForm",
"key": "enter",
"when": "calva:keybindingsEnabled && calva:outputWindowActive && calva:outputWindowSubmitOnEnter && editorTextFocus"
},
And Calva sets the calva:outputWindowSubmitOnEnter
to false when the cursor is not behind the top level form. To get the behaviour you want, @U01EB0V3H39, undefine the default keyboard shortcut and define it again without that context variable.Ah it was this I’m thinking of: https://github.com/BetterThanTomorrow/calva/issues/1578
The video of Joyride demos a really handy addition to Calva, commenting out an Sexp with #_
. Is there any chance that functionality will just be included in Calva in the future? Or do I need to roll my own script (following the video) to get that feature?
Maybe Calva could be contributing a selection of Joyride scripts? 😀 Only half joking, this could actually be a thing, generally. But to answer your question. I think there might be an issue about this. I would merge a PR implementing it properly. As the video shows, it is not all that much to it. And it's even easier in Calva.
can afterCLJReplJackInCode
take in multiple commands? I would like to start the server with (start)
but I would also like to require portal, open it and bind tap to submit. Would afterCLJReplJackInCode
be the right place to do this or elsewhere?
Calva displays ClojureDocs examples in tooltips. We love that. 😍
What if we could also add our own examples exported from either of e.g.
• ^{:examples '(...)}
• (comment ...)
RCF comments
• (hyperfiddle.rcf/tests ...)
RCF tests
In the screenshot, note how I repeated one of my rcf/test
cases in the docstring manually. It would be great to be able to import a comment form automatically instead!
Does Calva already support this kind of automatism?

@U2DART3HA I see your :thinking_face:. Nice to see the first reaction to my question come from a maintainer of hyperfiddle/RCF. 🙂
I'm currently working on wrapping third-party lib APIs more automatically. Here we see no wrapping bodies, but a prototype of how docstrings could follow.
Hehe I think this is a great idea 😄 I hear "Show me an example" 10 times a day. Most of the time, finding the example damages the communication. It would be effective to just point (my mouse) at the example.
I suppose we could envision e.g.
(defn foo [] ...)
(rcf/doctests foo ...)
(rcf/tests ...more tests...)
where only doctests would be added to the tooltip.
Or, maybe better, an instrumentation to read the top-level forms and add the first rcf/tests form following a defn to its docstring.
Not sure yet.I’d separate documenting from testing.
(defn foo [] …)
(rcf/example foo (rcf/tests …))
;; or
(rcf/document foo (rcf/tests …))
Could this Calva popup be customized to display other var meta than :doc
?
Ok so the (rcf/tests ...)
inside (rcf/document for ...)
would be somehow added to foo's docs?
Calva's popup seems to be pluggable somehow. Looking at https://github.com/BetterThanTomorrow/calva/blob/d12ea27fc193aa3001dcf8658d238ed88648ce7f/src/clojuredocs.ts...
So it would be possible to inject RCFdocs between the docstring and the ClojureDocs examples in the hover tooltip. 🙂
But of course, if Calva automatically did that for an e.g. :examples
metadata key, this might be a perfect and easy hook for anyone to use, not just hyperfiddle/rcf.
Have you had a look at custom repl hover snippets? Might be what you are looking for.
Something like this?
{
"name": "RCF show example",
"repl": "clj",
"snippet": "(:hyperfiddle.rcf/example (meta #'$top-level-defined-symbol))"
}
I guess it would need some pretty printing tooComing back here and re-reading about hover snippets, I deleted my last comments. I think I understand that they might be a working solution. They seem https://github.com/BetterThanTomorrow/calva/blob/d12ea27fc193aa3001dcf8658d238ed88648ce7f/src/providers/hover.ts#L26-L50.
Yes, it is even documented. 😃 https://calva.io/custom-commands/#custom-repl-hover-snippets
Please let us know if/how it works. This is really just a first implementation of this and we are dying for some user feedback. @U02EMBDU2JU is who had the idea and the persistence to implement it.
Getting somewhere, but can't yet find how to (-> var meta :examples)
it without it failing.
Maybe easier to define a function in the project that you call with $hover-text
and $ns
as arguments? Then you can inspect what you get there and rule see if it is Calva feeding your garbage. Also quicker to REPL your way to the hover you want to have that way.
I can't manage to get hover snippets to run. I’m on 2.0.269. Command snippets do run.
"calva.customREPLHoverSnippets": [
{
"name": "eval text on hover",
"repl": "clj",
"snippet": "(str \"🚀\" \"$hover-text \")"
}
],
Starting small like this helped me, Geoffrey, and step 2 (click in other file) seems to be really necessary before hovering picks up changes from settings.
@U2DART3HA it could be that you're not getting the quoting right and the thing blows up in the REPL silently. Tried with something really simple?
Outside of the ”something really simple” space, Calva has these in a test project and they work:
"calva.customREPLHoverSnippets": [
{
"name": "edn hover hover-text",
"snippet": "(str \"**JSON hover hover-text** \" \"$hover-text\")"
},
{
"name": "Show doc string",
"snippet": "(clojure.string/replace (with-out-str (clojure.repl/doc $hover-text)) \"\n\" \"\n\n\")"
}
],
If they don't work for you, @U2DART3HA, then something is probably wrong.And these too in .calva/config.edn
:
{:customREPLHoverSnippets
[{:name "edn hover symbol"
:snippet "(str \"**EDN edn hover symbol**: \" $hover-text)"}
{:name "edn hover symbol quoted"
:snippet "(str \"**EDN edn hover symbol quoted** \" '$hover-text)"}
{:name "edn hover hover-current-form"
:snippet "(str \"**EDN edn hover hover-current-form** \" \"$hover-current-form\")"}
{:name "edn hover show val"
:snippet "(str \"### EDN show val\n
clojure\n\" (pr-str (eval (symbol (str \"$ns\" \"/\" \"$hover-top-level-defined-symbol\")))) \"\n\")"}
{:name "edn hover current-form"
:snippet "(str \"**EDN edn hover current-form** \" \"$current-form\")"}]}
Don't you also which we could define this as clojure data, instead of strings? 😃Hover Snippets in config.edn
works. But not in "calva.customREPLHoverSnippets"
in settings.json
This is my whole settings.json
{
"calva.customREPLHoverSnippets": [
{
"name": "eval text on hover",
"repl": "clj",
"snippet": "(str :hello)"
}
]
}
As for me I got back my REPL debugging abilities. It's stable but I can't get the evaled symbol to be recognized by var
.
Need to sign off now. Thanks a lot for the help till now!
I managed to get something 😄
But still no luck with calva.customREPLHoverSnippets
, even without the "repl"
key.
(defn ^{:examples '(:hello-world! {:an "example"})} hi
"Docstring."
[who]
(str "😂 hello " who))
(defn examples-for [some-ns some-ts]
(def some-ns some-ns)
(def some-ts some-ts)
(try
(str "
clj\n" (-> (str some-ns "/" some-ts) symbol resolve meta :examples) "\n")
(catch Exception e (ex-message e)))
;;
)
(examples-for "some.ns" "hi")
"calva.customREPLHoverSnippets": [
{
"name": "add :examples metadata to tooltip",
"repl": "clj",
"ns": "your.ns",
"snippet": "(examples-for \"$ns\" \"$hover-text\")"
}
],
@U2DART3HA, please file an issue on Calva, from the VS Code help menu. It will attach some system info that might be relavant.
Hi hope you find what ails you Geoffrey!!!
Thanks for sharing your struggles, @U0514DPR7!
This will make for a nice week-end. 🥳 🥂 Thanks again for the help and comments!
@U0ETXRFEW, thank you for your support. I’d like to dig further into the issue before reporting it. I believe there is an issue, but I cannot prove it is not related to my config yet.
One thing to test is if it is the same in a minimal deps.edn project. You can also run Calva in dev mode and try catch where hover snippets are processed in the debugger. It's pretty quick to get started: https://github.com/BetterThanTomorrow/calva/wiki/How-to-Hack-on-Calva
It's great to see people starting to use this feature! I've been meaning to write about it and add more documentation, but yeah... I've found it helpful to build the functionality I want without the hover first and then just pasting it in. I'll try to add some better debugability into the snippets, i.e. optionally showing what is being eval'd on hover. @U2DART3HA have you tried running the "Reload extension host" command or restarting vscode? Sometimes changing settings.json does weird things and a reload fixes that. (not that this is a good long term solution 🙂 )
I think that rather than pasting the functionality into the hover when finished with building it, is to make it a function and then just call that one from the snippet. Then updating the contribution is a matter of updating the function rather than updating a string full of backslashes.
I did restart VScode. I now believe the issue is external to Calva.
Solidified my code a bit. Quite hard to debug but this seems to work quite well now.
(ns util.repl
(:require [hyperfiddle.rcf :as rcf]))
(defonce ^:private no-examples-found "No examples (either namespace is unloaded, or no `:examples` medatada found).")
(defonce ^:private examples-prefix "## Examples\n
clj\n")
(defonce ^:private examples-suffix "\n")
(defn- markdown-for-examples [e]
(str examples-prefix e examples-suffix))
(defn ^{:examples '(:hello/world {:of "examples!"})}
examples-for
"Returns `:examples` metadata for a var from its namespace and name, or `nil`."
[^String a-ns ^String a-name]
(let [examples (try
(some-> (str a-ns "/" a-name)
symbol
resolve ; tried requiring-resolve to auto-require-on-hover-in-unloaded-files, but didn't work.
(#(when (var? %) %))
meta
:examples)
(catch Exception e (ex-message e)))]
(if examples (markdown-for-examples examples) no-examples-found))
;;
)
(rcf/tests
(examples-for "clojure.core" "inc")
:= no-examples-found
(examples-for "util.repl" "examples-for")
:= (markdown-for-examples "(:hello/world {:of \"examples!\"})")
;;
)
"calva.customREPLHoverSnippets": [
{
"name": "show :examples metadata in hover tooltip",
"repl": "clj",
"snippet": "(do (require 'util.repl) (util.repl/examples-for \"$ns\" \"$hover-text\"))"
}
],
And when symbol hovered doesn't satisfy requirements:
Nice @U0514DPR7! Is there anything in the API that could be better?
This is wonderful stuff, @U0514DPR7!
Thanks Lukas! The documentation could encourage us (everywhere in VS Code's settings.json
file where we can write clojure code) to always just call a clojure function that we'll be able to debug, just like Peter wrote above last week.
Still in settings.json
, it's never been clear to me when the "ns"
key is going to be sufficient, or I'll need to require
my ns manually in the snippet. I always (I think) end up needing to manually require, like in the above.
Apart from that, Lukas, I'm not sure if it's a good ask, but if we could say: activate this hover only over var
s, this might be helpful. Not sure.
Interesting suggestion. We’ve got a bunch of possible substitutions, but having some kind of :predicate
key or similar might be nice. You can of course already kind of do it by checking the contents of the substitution but like you said, triggering only on certain things is probably something most people would want.
I'm getting quite out of time with my employer to work on this, but I can finally report significant, useable progress.
The with-rcf-tests!
macro is based on what @U2DART3HA showed us last Friday, although slightly differently.
Note that it does execute the doc-test-examples with RCF, so it serves both purposes of auto-testing with RCF, and setting up a var's examples metadata for Calva's hover snippets.
Note how I cooked up a quick, inelegant \n
-based solution to have newlines in the markdown rendering. Didn't spend time thinking about how to do better.
I'm also pasting the entire util code in its current state, in case someone wants to experiment some more.
"calva.customREPLHoverSnippets": [
{
"name": "show :examples metadata in hover tooltip",
"repl": "clj",
"snippet": "(do (require 'util.examples) (util.examples/of \"$ns\" \"$hover-text\"))"
}
],
(ns util.examples
(:require [clojure.string :as str]
[hyperfiddle.rcf :as rcf]))
(defonce ^:private no-examples-found "No examples (either namespace is unloaded, or no `:examples` medatada found).")
(defonce ^:private examples-prefix "## Examples\n
clj\n")
(defonce ^:private examples-suffix "\n")
(defn- markdown-for-examples [e]
(str examples-prefix e examples-suffix))
(defonce test-example '(:hello/world {:of "examples!"}))
(defmacro with-rcf-tests! [var-sym & examples]
(alter-meta! (resolve var-sym) assoc :examples examples)
`(rcf/tests ~@examples))
(defn
of
"Returns `:examples` metadata for a var from its namespace and name, or `nil`."
[^String a-ns ^String a-name]
(let [maybe-var (try
(some-> (str a-ns "/" a-name)
symbol
requiring-resolve
(#(when (var? %) %)))
(catch Exception e
(ex-message e) ; inspect it at the REPL when needed...
nil ; ignoring entirely the ex-message
))
maybe-examples (try
(some-> maybe-var meta :examples)
(catch Exception e
(ex-message e) ; inspect it at the REPL when needed...
nil ; ignoring entirely the ex-message
))]
(cond maybe-examples (markdown-for-examples maybe-examples)
(and maybe-var
(str/starts-with? a-ns "clojure.")) ""
maybe-var no-examples-found
:else "")))
(with-rcf-tests! of test-example)
(rcf/tests
(of "clojure.core" "inc")
:= ""
(of "yada.util.repl" "of")
:= (markdown-for-examples test-example)
;;
)
(defn join-not-blank
"Like `clojure.string`'s `join` but does not separate `blank?` items in `coll`."
([coll]
(str/join (remove str/blank? coll)))
([separator coll]
(str/join separator (remove str/blank? coll))))
(examples/with-rcf-tests!
join-not-blank
"\nWe don't like this about str/join...\n"
(str/join "🧱" ["a" "" nil "b"]) := "a🧱🧱🧱b"
"\nThis implementation uses `(remove str/blank? coll)`...\n"
(join-not-blank "🧱" ["a" "" nil "b"]) := "a🧱b")
(rcf/tests
"After blank handling, it delegates to `str/join`."
(join-not-blank ["a" "" nil "b"]) := "ab"
(join-not-blank "🧱" []) := ""
(join-not-blank []) := ""
;;
)
This updated macro solves a bit the whitespace issue.
(defmacro with-rcf-tests! [var-sym & examples]
(if-let [v# (resolve var-sym)]
`(do
(alter-meta! ~v# assoc :examples ~(str/join "\n" examples))
(rcf/tests ~@examples))
`(println "🟥 " ~var-sym " could not be resolved and will not be tested with " ~(str/join "\n" examples))))
Of course this could be improved a lot more.
I begin to be sorry about pinging you for each update.
Might be time to stop that.Please don't stop updating, @U0514DPR7! I learn so much from these updates. About macros, about nitty gritty details, about this feature, and so on. As I said before, I think you have awesome material for blog content here. My love for the REPL grows reading these updates. 😃 ❤️
Understood, Peter!
BTW to make it clear, why I share this code (use it as public domain code) like this is b/c some of you might want to see opportunities to push this further, faster or somewhere else than me. We might all benefit from this. You’re entirely allowed to run with it!
Also, my job responsibilities make it pretty hard for me to be relentlessly devoted to pursuing something like this to its optimum in a short span of time.
Although I’d like to refine more the tooltip formatting, my next steps are to think about wrapping all our uses of RCF and these test-doc-examples in a single namespace e.g.
• tests/with-rcf
and
• tests/with-rcf-examples
, to provide a more uniform interface and auto-complete experience to my team.
OTOH if hyperfiddle/rcf adds its own e.g. document
macro soon, I might instead continue relying directly on RCF with the team.
Cheers!
Needed to check if we can have syntax coloring. We can! Also improved a bit on line feeding and string handling. This snippet only contains redefinitions of changed forms in the bigger snippet above.
(defonce ^:private examples-prefix "## Examples\n
\n")
(defn- str-encode [s]
(if (string? s) (clojure.core/format "\"%s\"" s) s))
(defn- ->str [examples]
(str/join "\n" (map str-encode examples)))
(defmacro with-rcf-tests [var-sym & examples]
(if-let [v# (resolve var-sym)]
(do
(alter-meta! v# assoc :examples (->str examples))
`(rcf/tests ~@examples))
(println ":large_red_square: " ~var-sym " could not be resolved and will not be tested with " ~(->str examples))))
``
This new version of the with-rcf-tests
drops the bang !
from the end of its name, so anyone calling it needs to refactor the call sites...Awesome !
Finally I have worked on quite a round of refactoring yesterday.
Today, getting back to my main objective again, I realized that the hovers don't seem to know how to detect code from other namespaces! Do you have suggestions how to do it without embarking in a :ns
form parsing adventure?
Screenshots in this order:
• When symbol hovered is in same file/ns
• When symbol hovered is in another file/ns + some debugging
• Calva's current API
In other words, something that would give the ns of the symbol at point.
In the 2nd screenshot:
1. I'm in yada.util.wrap
,
2. writing test examples for yada.util.wrap/adapt-meta
, and
3. using (yada.util.)examples/with-rcf-tests
to do so, and
4. if I hover that, I'd love Calva to offer me a substitution so that
5. I may know that with-rcf-tests
6. is from examples
, which is in fact
7. `yada.util.examples`.
So what would be very valuable are knowing points 5 and 7.
Hmm, I might have a solution for it... I'd need to ignore $ns
and ask the REPL to describe me the evaled text itself...
@U0514DPR7 All the replacements calva gives you are based on the text, so it doesn't actually have the information you need. But you are right, you can ask the repl for the metadata of the var. The other possibility would be to ask clojure-lsp/clj-kondo. Or Calva could either of them for you and present a richer set of substitutions, but I'm not sure if that's really needed.
Lots of unit tests and manual tests later, I think I've got "all" situations covered.
The latest situation to resolve (when hovering a symbol whose qualified name is from a require aliased), after quite a few hours of head-banging, was fixed with (mostly) the 2nd screenshot in settings.json
.
Now that this is ready I'll start using it more and refining the code and moving each function to another namespace when it's pertinent to do so, and then this solution will become harder to share with you people.
The current code will help me implement wrappers for instrumenting other things, not just code examples. A great idea might be to show auto-expand snippets related to the hovered symbol!
A next step is to confirm with my boss in what form I might share back for you what I've got now. It took me quite a bit more time to implement this and I feel pressed to deliver the next bits without spending too much time "with you" now...
what do you mean by “auto-expand snippets”?
VS Code's or IDE's user snippets, e.g. typing func
proposes this expansion...
This one above could be linked to defn
's metadata to be advertised as available for your next times you write defns.
Teams would learn snippet-based productivity much faster if snippets were discoverable in hover tooltips.