Fork me on GitHub

How can I jack in UNDER an interactive shell.


Currently, the clojure command is directly invoked by calva.


I’d prefer run clojure in an interactive shell so that it can inherit the environment variales I set in the shell.


There is a command for copying the jack-in command line. Then you can run it in a terminal and instead of jack-in you use connect to a running repl.


You can also start VS Code from a terminal and use jack-in.


There are also settings for setting environment variables for the jack-in process.


> You can also start VS Code from a terminal and use jack-in. This does inconvenient when we want to open the project with open recent project in vscode


> There are also settings for setting environment variables for the jack-in process. This goes out of the sync with environment configurations such as direnv etc.


Better if it would be possible that Calva can start the repl in a shell.


Or is it possible that I can change the clojure command to something else like myclojure which is basically a wrapper the sources the shell rc and invokes the real cojure?


Don't know. Sounds like it could work, but also like it could get confusing.


I would put the Calva jack-in command line in a shell script and use that to start my repl, then connect Calva.


It has the extra benefit that you can reload the VS Code window without killing your repl.


> Don’t know. Sounds like it could work, but also like it could get confusing. I feel the least unsurprising way is that there is not difference when we launch the clojure repl from terminal or within Calva.


the least surprising


It's hard to achieve. The pseudo-terminals is the only API that give Calva the access to the process output it needs to control the REPL start and connection. It will mean that Calva starts the REPL with the same environment as VS Code has, plus any jackInEnv you give it. For devs who need something else, there is Connect to a running REPL.


Thanks for the info! I feel the most flexible way may be to specify the alternative clojure binary to execute. E.g., myclojure.


I'm curious how you fare. Could be something we should add to the docs.


Sorry, fare?


I must first check the dictionary that I am using it correctly (not a native speaker) 😃


Yeah I think it is sort of right. 😃 Anyway, just meant that I am curious to hear about your results from solving it with a wrapper script.


I’d like have a try if the clojure command name can be changed to another name (without change the repl connection sequence shipped with calva, otherwise it would simply be a hack). Having two executables with the same name clojure makes things complicated.


That's what I meant by confusing. But maybe if your script is named clojure and it uses the real clojure by a fully qualified path, and you make sure VS Code starts with an environment that finds your clojure first. Even so, I'm suspecting you might run into weird quoting issues.


I tested this python script, which works fine.

#!/usr/bin/env python

This wrapper is mainly to leverage direnv env variables under vscode.
Calva, due to the vscode api limitation, launches `clojure` outside the fish shell, so we use this wrapper
to source the shell variables (with direnv exec).

import subprocess
import sys
import os.path as osp
import os

def get_env():
    env = dict(os.environ)

    # remove the path this wrapper belongs to.  only `dotfiles/bin` or the `.` dir can potentially
    # contain our clojure wrapper.

    # assumption: there shall ALWAYS be a colon after the replaced path in the original $PATH env
    env["PATH"] = env["PATH"].replace(osp.expanduser("~/.dotfiles/bin") +":", "")
    # XXX also remove the current working directory path (".")
    env["PATH"] = env["PATH"].replace(".:", "")
    return env

def main():
    env = get_env()
    # adjust sys.argv to make the executable 
    # ./clojure => clojure
    # ~/.dotfiles/bin/clojure => clojure
    sys.argv[0] = "clojure"
    # sys.argv[0] = "/opt/homebrew/bin/clojure"

    # print(env["PATH"], flush=True)
    # print(sys.argv, flush=True)

    # use `direnv exec` to execute
    argv = ["direnv", "exec", os.getcwd()] + sys.argv
    # execvpe will use env["PATH"] to search for "direnv"
    os.execvpe(argv[0], argv, env)

if __name__ == '__main__':


The python script is named as clojure and sits in the PATH before the real clojure executable.


Nice. If you put that in a gist we can link to it from the Calva docs.


I've started up VSCode into a shadow.cljs project. I attempt to jack-in, but I'm getting the following error:

npx.cmd shadow-cljs -d cider/cider-nrepl:0.27.4 watch :app
shadow-cljs - config: c:\Users\fadrian\Projects\atlas\shadow-cljs.edn
shadow-cljs - connected to server
shadow-cljs - watching build :app
already started
{:build-id :app}
ExceptionInfo: already started
        shadow.cljs.devtools.server.supervisor/start-worker (supervisor.clj:27)
        shadow.cljs.devtools.server.supervisor/start-worker (supervisor.clj:19)
        shadow.cljs.devtools.api/start-worker (api.clj:117)
        shadow.cljs.devtools.api/start-worker (api.clj:113)
        shadow.cljs.devtools.api/watch* (api.clj:187)
        shadow.cljs.devtools.api/watch* (api.clj:173)
        shadow.cljs.devtools.server/watch-builds (server.clj:572)
        shadow.cljs.devtools.server/watch-builds (server.clj:555)
        shadow.cljs.devtools.server/from-cli (server.clj:628)
        shadow.cljs.devtools.server/from-cli (server.clj:592)
        clojure.lang.Var.applyTo (
        clojure.core/apply (core.clj:667)
        clojure.core/apply (core.clj:662)
        shadow.cljs.devtools.cli-actual/lazy-invoke (cli_actual.clj:23)
        shadow.cljs.devtools.cli-actual/lazy-invoke (cli_actual.clj:20)
        shadow.cljs.devtools.cli-actual/blocking-action (cli_actual.clj:129)
        shadow.cljs.devtools.cli-actual/blocking-action (cli_actual.clj:116)
        shadow.cljs.devtools.cli-actual/main (cli_actual.clj:177)
        shadow.cljs.devtools.cli-actual/main (cli_actual.clj:132)
        clojure.core/apply (core.clj:671)
        clojure.core/apply (core.clj:662)
        shadow.cljs.devtools.cli-actual/from-remote (cli_actual.clj:210)
        shadow.cljs.devtools.cli-actual/from-remote (cli_actual.clj:201)
        clojure.lang.Var.invoke (
        shadow.cljs.devtools.cli/from-remote (cli.clj:79)
        shadow.cljs.devtools.cli/from-remote (cli.clj:77)
        shadow.user/eval35027 (NO_SOURCE_FILE:1)
        shadow.user/eval35027 (NO_SOURCE_FILE:1)
        clojure.lang.Compiler.eval (
        clojure.lang.Compiler.eval (
        clojure.lang.Compiler.eval (
        clojure.core/eval (core.clj:3202)
        clojure.core/eval (core.clj:3198)
        shadow.cljs.devtools.server.socket-repl/repl/fn--15909 (socket_repl.clj:61)
        clojure.main/repl/read-eval-print--9110/fn--9113 (main.clj:437)
        clojure.main/repl/read-eval-print--9110 (main.clj:437)
        clojure.main/repl/fn--9119 (main.clj:458)
        clojure.main/repl (main.clj:458)
        clojure.main/repl (main.clj:368)
        shadow.cljs.devtools.server.socket-repl/repl (socket_repl.clj:28)
        shadow.cljs.devtools.server.socket-repl/repl (socket_repl.clj:26)
        shadow.cljs.devtools.server.socket-repl/connection-loop (socket_repl.clj:102)
        shadow.cljs.devtools.server.socket-repl/connection-loop (socket_repl.clj:72)
        shadow.cljs.devtools.server.socket-repl/start/fn--15924/fn--15925/fn--15927 (socket_repl.clj:142) (
Jack-in process exited. Status: 1
I've tried shutting down VSCode and starting/jacking in again, but I get the same error each time. Any ideas on how to clear this error and get a REPL up?


If you don't have other java processes something like killall java might do the trick. Otherwise I think it could be a matter of using ps -ef | grep java and combine with lsof -p <pid> to find the process to kill. Or maybe lsof <project dir> | grep java is enough...


Sorry - I should have added that I'm running this on a Windows box.


I just did as you recommended and killed off all java processes. Things are starting up again.


Thanks for your help

🙏 1

I wouldn't have known how to do it on Windows. 😃 But if you have WSL, I think the commands I suggested might work.


I do have WSL. I just don't use it much because I'm developing stuff that runs mainly on Windows. :face_with_rolling_eyes:


In any case, thanks again.


And we now have a first real integration test for Calva! It tests that Calva can start a REPL and connect it. Sooooo goooooooddd!!! Thanks, @domagala.lukas! ❤️ gratitude ❤️ gratitude ❤️ gratitude It would be super good for the project if people figured about some things that should be tested like this in CI.

calva 4
🎉 3
gratitude 1
catjam 3

Haha, @U02N27RK69K. Let's see if your PR passes the integration tests. 😃

Cora (she/her)16:02:33


Cora (she/her)16:02:11

it works 😄

clojure-spin 1
Grant Horner16:02:56

Hey guys! Not sure if this is already reported, but I’m having an issue choosing how to resolve macros. The options in the bottom right of the screen are too small to read, and mousing over doesn’t provide any sort of tool tip. I tried changing a few font sizes in the settings but couldn’t find any that affected it. Any thoughts?

Grant Horner16:02:43

Nvm, I guess I was just being impatient, you do get a tooltip on hover. Still, might be nice to fix the font?


VS Code has no such API to change fonts on those things. But maybe there is some other widget that can be used. Like a quick pick menu seems more appropriate. Do we have a way to control that, @UKFSJSM38, @U9A1RLFNV?


Please file this as an issue on Calva, @U02RXJVMKNE

👍 1

Yes, the default on vscode IMO is terrible.. but we can override the window/showMessageRequest handler on calva and ask just like calva ask what project type when jacking in the repl


Cool. They are called Quick Pick Menus in VS Code speak. 😃


Yeah, before clojure-lsp started handling this for us, Calva actually opened a quick pick menu.

👍 1
😂 1

So if we can get the options from clojure-lsp to show in the quick-pick and override the default, that would be good.


Something like so. 😂

😅 5
Cora (she/her)20:02:10

actually now I need to do some real, heavy work that messes with types

Cora (she/her)20:02:15

@pez I was thinking I could go file by file, turning on the eslint linters, fixing types in general, and writing tests where possible. that way it's a gradual solidifying of things and not these huge PRs


Checking, will typing still be optional according to your plan here? I kinda appreciate that part of TypeScript, that I can reach for types when I want them and skip it when they make it harder for me to experiment.

Cora (she/her)20:02:46

it can be a part of it, yes. you basically need to allow implicit and explicit "any" then, since the any type is basically "yolo! i hope you know what you're doing!!"

Cora (she/her)20:02:03

you can also always disable typescript for individual lines or files, even temporarily


Implicit any sounds good to me.

Lukas Domagala21:02:54

runs to finish his PR before the big change

😅 1
Lukas Domagala23:02:19

I’ll have a look now.

💜 1
Lukas Domagala00:02:03

done. added three comments, but looks good 🙂 thanks!

💜 1
Cora (she/her)22:02:45

I still have a big, outstanding pr

Cora (she/her)22:02:04

so hopefully yours gets merged first

Lukas Domagala23:02:52

Is there a way to find out why the linter sometimes really likes new lines? This seems like overkill, we’re not writing python 😉

return newSnippets.concat(
            (item) =>
                    (newItem) => ===
                ) !== -1


I've also found this a bit aggressive from the formatter. For some reason I find it hard to read. But maybe I can learn. And maybe it is good way for the formatter to suggest a small refactor, like @U02N27RK69K noted.