Fork me on GitHub
#calva
<
2022-04-29
>
orestis08:04:32

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?

orestis08:04:33

Essentially I guess I'm asking for: 1. Access to the file system 2. Ability to execute commands from other extensions (calva, portal, etc)

pez09:04:01

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.

borkdude09:04:53

@U7PBP4UVA 1 is certainly possible. see the examples directory, there is a terminal.cljs file in there

borkdude09:04:17

2. @U0ETXRFEW maybe Calva could export an extension function for this or so?

borkdude09:04:29

3. yes, this is possible, with showInformationMessage

pez09:04:04

> 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. 😃

👍 2
👀 1
orestis09:04:15

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!

metal 3
Erick Isos14:05:25

The “play sound” is possible? :shocked_face_with_exploding_head:

Max16:04:34

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 typed

pez16:04:49

The 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.)

Max16:04:03

Will do!

pez16:04:19

Actually, that's already there... I don't understand why it doesn't work. Maybe it is some other widgetVisible we need to exclude...

rayat16:04:08

Is eval by default set to enter ?

Max16:04:28

Is anyone else able to replicate? I wonder if this is a weird thing with my setup

pez16:04:30

Actually it wasn't there, never mind me... Go ahead with the issue, @U01EB0V3H39 😃

partyparrot 1
pez16:04:14

The other behaviour is intended. If the cursor is behind the top level form enter submits. Otherwise inserts an enter.

1
pez16:04:46

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.

🙏 1
pez16:04:44

And I think you now have clues to how to fix the bug you posted about. 😃

bringe17:04:44

I thought Calva already had something added to handle the suggestion and eval case…

bringe17:04:58

I don’t remember the intention though or what was added

Luke Johnson17:04:18

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?

1
4
🙂 1
1
🙏 1
pez18:04:54

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.

3
jdf18:04:33

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?

pez18:04:55

I think that should work well.

👍 1
Daniel Jomphe19:04:07

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?

1
calva 1
Daniel Jomphe19:04:09

@U2DART3HA I see your :thinking_face:. Nice to see the first reaction to my question come from a maintainer of hyperfiddle/RCF. 🙂

Daniel Jomphe19:04:47

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.

Geoffrey Gaillard19:04:38

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.

🙂 1
Daniel Jomphe19:04:56

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.

Geoffrey Gaillard19:04:25

I’d separate documenting from testing.

(defn foo [] …)

(rcf/example foo (rcf/tests …))
;; or
(rcf/document foo (rcf/tests …))

Geoffrey Gaillard19:04:30

Could this Calva popup be customized to display other var meta than :doc?

Daniel Jomphe19:04:07

Ok so the (rcf/tests ...) inside (rcf/document for ...) would be somehow added to foo's docs?

Daniel Jomphe19:04:17

So it would be possible to inject RCFdocs between the docstring and the ClojureDocs examples in the hover tooltip. 🙂

Daniel Jomphe19:04:18

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.

pez19:04:52

Have you had a look at custom repl hover snippets? Might be what you are looking for.

👀 1
1
Geoffrey Gaillard19:04:11

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 too

Daniel Jomphe20:04:34

Coming 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.

pez20:04:11

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.

Daniel Jomphe20:04:32

Getting somewhere, but can't yet find how to (-> var meta :examples) it without it failing.

pez21:04:51

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.

Geoffrey Gaillard21:04:17

I can't manage to get hover snippets to run. I’m on 2.0.269. Command snippets do run.

Daniel Jomphe21:04:06

"calva.customREPLHoverSnippets": [
    {
      "name": "eval text on hover",
      "repl": "clj",
      "snippet": "(str \"🚀\" \"$hover-text \")"
    }
  ],

Daniel Jomphe21:04:48

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.

pez21:04:37

@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?

pez21:04:57

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.

pez21:04:45

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? 😃

Geoffrey Gaillard21:04:41

Hover Snippets in config.edn works. But not in "calva.customREPLHoverSnippets" in settings.json

Geoffrey Gaillard21:04:01

This is my whole settings.json

{
  "calva.customREPLHoverSnippets": [
    {
      "name": "eval text on hover",
      "repl": "clj",
      "snippet": "(str :hello)"
    }
  ]
}

pez21:04:12

How very strange. Have you tried w/o the "repl" key?

Daniel Jomphe21:04:15

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 .

Daniel Jomphe21:04:27

Need to sign off now. Thanks a lot for the help till now!

Geoffrey Gaillard21:04:01

I managed to get something 😄

Geoffrey Gaillard21:04:31

But still no luck with calva.customREPLHoverSnippets, even without the "repl" key.

Daniel Jomphe21:04:07

Needed to resolve

👏 1
Daniel Jomphe21:04:47

(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\")"
    }
  ],

pez21:04:11

@U2DART3HA, please file an issue on Calva, from the VS Code help menu. It will attach some system info that might be relavant.

Daniel Jomphe21:04:54

Hi hope you find what ails you Geoffrey!!!

pez21:04:57

Thanks for sharing your struggles, @U0514DPR7!

Daniel Jomphe21:04:23

This will make for a nice week-end. 🥳 🥂 Thanks again for the help and comments!

🥃 2
Geoffrey Gaillard22:04:13

@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.

pez22:04:49

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

👍 1
Lukas Domagala10:04:06

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 🙂 )

😍 1
👍 1
pez10:04:45

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.

Geoffrey Gaillard20:04:53

I did restart VScode. I now believe the issue is external to Calva.

Daniel Jomphe21:05:03

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\"))"
    }
  ],

👍 1
Daniel Jomphe21:05:49

And when symbol hovered doesn't satisfy requirements:

Lukas Domagala21:05:05

Nice @U0514DPR7! Is there anything in the API that could be better?

pez21:05:05

This is wonderful stuff, @U0514DPR7!

Daniel Jomphe21:05:21

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.

Daniel Jomphe21:05:58

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.

Daniel Jomphe21:05:13

Apart from that, Lukas, I'm not sure if it's a good ask, but if we could say: activate this hover only over vars, this might be helpful. Not sure.

Lukas Domagala21:05:05

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.

Daniel Jomphe20:05:05

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       []) := ""
 ;;
 )

👋 1
1
Daniel Jomphe09:05:46

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.

pez09:05:45

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. 😃 ❤️

☺️ 1
1
Daniel Jomphe11:05:53

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!

🙏 1
👍 1
Daniel Jomphe15:05:32

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...

Daniel Jomphe13:05:03

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

Daniel Jomphe13:05:21

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.

Daniel Jomphe13:05:31

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...

Lukas Domagala11:05:20

@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.

Daniel Jomphe21:05:38

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...

Lukas Domagala12:05:36

what do you mean by “auto-expand snippets”?

Daniel Jomphe14:05:29

VS Code's or IDE's user snippets, e.g. typing func proposes this expansion...

Daniel Jomphe14:05:44

This one above could be linked to defn's metadata to be advertised as available for your next times you write defns.

Daniel Jomphe14:05:13

Teams would learn snippet-based productivity much faster if snippets were discoverable in hover tooltips.