Fork me on GitHub

Hi there, I'm using calva for a client server project (in fulcro) and have two windows open for the two REPLs per They both use .calva/output-window/output.calva-repl for their output, and consequently trample each other, and get me a little confused 🙂 . Is there a way to keep them separate? The closest I can see in the docs to anything about this is this passage in revision 947a9fa7 at

If you save the output/REPL file (which most often does not make much sense, but anyway) you will sometimes be presented with a message about VS Code being confused about the file contents being out of sync. Just choose to Overwrite the currently saved version and you should be fine.


Yes, this is unfortunate. We are tracking it here:


thanks @U0ETXRFEW wasn't sure if I'd just missed something in the docs. Somehow I missed that issue. 🙂


Consider running both client and server dev in the same VS Code window. That’s what I prefer. Still same output window, but less confusing.

👍 2

I renamed that issue now as it was suggesting a solution rather than stating the problem. I think you would have found it as it is named now.


ah, interesting. I think I was trying to do that, but wasn't able to run and jack-in to multiple repls. I landed on the two windows approach thanks to a link here: (now closed, favouring:, Do you have a solution for multiple jack-ins that I've missed?


Calva does support 2, #76 is about it being more than that. 😃 We should probably revisit the descriptions.


i HAVE missed that! 😄


I use the shadow-cljs project type. And make shadow use deps.edn for dependenies with a :deps {:aliases […]} entry.


ah, some more fine work by holyjak and yourself that I'd missed! Double thanks! 🙂

😊 1

We should update the Calva docs also. I guess we derailed you here?


I'm afraid I've been derailed too long to have a firm memory of exactly how it happened 😉 It's possible. 🤷


I think the shadow-cljs centric approach might break down at some point, @U0522TWDA had some thoughts around that. I am pretty sure the deps.edn + shadow-cljs project type can be made to works as well, but we haven’t quite gotten control of all the moving parts yet.


ah yes. this "some projects need special handling by the user." and "See for tips about how to open the same project folder in two separate VS Code windows" ring a bell. The latter confirmed to me that the link in the closed 513 item was probably the right way, for now.


It is all written quite a while ago. We know much more now about how the different options are used and work.

🙇 1

@U0ETXRFEW while I've got your attention, I have another question that's in the REPL vicinity. On it says "Why would anyone want to use a Clojure editor without a REPL? It could be because you prefer some other REPL client over, like,", but by the end of the page, and even having read the Clover project readme, I'm no wiser as to why I might want to use it. 🙂 I do appreciate that given "Of course we encourage you to use Calva's REPL" you might not want to sell me on it, I think I only wonder because I stumbled across this while trying to solve the multiple repl stuff. and didn't feel i knew enough at the time to ask even a vaguely coherent question 🙂 Tl;dr; WHY might I want to use Clover?


"It is all written quite a while ago. We know much more now about how the different options are used and work." now you've got me imagining a mechanism whereby the docs have an age of creation vs the number of commits in the vicinity of features they talk about. It feels like something Knuth might've solved, and I just don't know about 🙂


That would be awesome.


I have no problem selling Clover over Calva on principle. Clover is quite different from Calva I think. But I haven’t used it so I don’t really know different how, and much less about why. @U04V70XH6 can maybe elaborate on that a bit.

👍 1

@U2LUY0P8B The main difference is that Calva's built-in REPL support relies on nREPL whereas Clover doesn't need nREPL and can work with a bare Socket REPL. We prefer that approach so that we don't need dependencies in our projects for REPLs -- a Socket REPL can be started in any Clojure process, just by providing a JVM option at startup, and we do in fact run REPLs in some QA and production processes. So our workflow with those processes is identical to how we work locally: the process with the REPL is started outside the editor and we can use Clover to connect to it and perform all the dynamic stuff (eval etc). So I have Calva's nREPL UI disabled but otherwise rely on all the static stuff that Calva provides (with LSP/clj-kondo/etc).

👍 1

In theory, I could use both Calva and Clover for dynamic stuff so that might be a good option for full-stack, with one of them connected to a Clojure REPL and the other to a ClojureScript REPL but then you'd need to ensure your eval key bindings were also separate and you'd have to remember which to use with which files 🙂

👍 1

Hi! First of all, thank you for your work, it is inspiring how far Calva has come in the past couple years! I have a minor question: it seems like exceptions thrown with (ex-info ,,,) do not display ex-data in the REPL output, is there something that can be done about it? maybe the ability to register a custom exception formatter?


Hi! Thanks for the words of encouragement!


I don’t quite remember what goes in ex-data. Custom formatters sounds nice, but might be a bit tricky to implement. The output window is just a file. Most of the stack trace handling is done from line 321 in this file:


You are welcome to file an issue describing what you lack and we can discuss there what options we have.


oh, I've actually found this issue already being submitted:


wasn't able to find the logic of Exception printing (which seems to be different from stacktrace printing) in the source you attached... (also there's no line 321, but that doesn't really matter)


Haha, yeah, I gave you the link to the commit where we implemented some of the stack trace printing.


Anyway, nice that you found the issue!


Is the latter screenshot there showing the ex-data?


no, the exception in the issue does not appear to have ex-data , here's one:


but when it is thrown, only the message is displayed:


If I evaluate

   (ex-info "The ice cream has melted!"
            {:causes             #{:fridge-door-open :dangerously-high-temperature}
             :current-temperature {:value 25 :unit :celsius}}))
And then evaluate *e I get
 {:cause "The ice cream has melted!",
  :data {:causes #{:dangerously-high-temperature
         :current-temperature {:unit :celsius, :value 25}},
    [[user$eval7203 invokeStatic "NO_SOURCE_FILE" 5]
     [user$eval7203 invoke "NO_SOURCE_FILE" 4]
So, that would mean that we should either have another button there, That does essentially the same thing as
(ex-data *e)
Or that we could include it in the stack trace print.


We currently only do what the button says it will do, and then also filter it some. But seems pretty easy to show more things. I just do *e when I want to see the whole thing, so have not thought so much about it.


that's certainly an opinionated matter, but for me it seems that ex-data belongs to the exception in the same way as the ex-message does, so it should be printed alongside it: either commented out below (as ex-message) or literally (as stacktraces, to be copy-able) I actually like your solution with accessing *e manually, and for many cases it will do, but unfortunately it doesn't seem to be able to work when connecting to an existing nREPL server, which throws exceptions in its main thread


Please add some context to that issue. I remember reading it, but didn’t understand what it was about then, because lack of Clojure knowledge and also didn’t see any ex-data there so got confused.


Checking, with that server that throws in the main thread, does Calva’s stacktrace print work?


sorry, that was nonsense about server's main thread, the exception handling there does not depend on Calva in any way


but when you connect to existing nREPL server and throw the exception from the REPL, I do indeed not have the button "print stacktrace", but can access *e which has all the data


That’s the opposite of what I thought you meant first. 😃


so, all the cases I can think of are covered with just accessing *e as you suggested, and the issue is not as critical as it first appeared to be, thank you for taking time to discuss it!

🙏 1

Calva always connects to an existing nREPL server. btw. So that could not be the distinguishing factor.


hm, yes, I see that you're launching a classic nREPL server from the Terminal, but somehow there's a difference in the absense of the "stacktrace" button (not critical, just for the record):


Maybe that server does not have the cider-nrepl dependencies?


ah, you're right, I mostly work from Cursive, so those are missing!


thanks again, that was an insightful conversation!


I’m starting to wonder if we should just use *e instead of cider-nrepl for this.


it indeed looks like all the needed information is already in *e