Fork me on GitHub

Dear Calva friends: • Tech debt mortgage:] • Maintenance: • Maintenance: Here the visible and beautiful change for users is adding commands for moving (and selecting) sexpr forwards/backwards moving past list boundaries if need to. Contributed by @jatkin. gratitude 🙏 The Tech debt one is @rayatrahman9 who is preparing for adding multi-cursor Paredit to Calva. (You read that right, more on this later). @rayatrahman9 has also upgraded our aging project to modern Node. And, (he is on fire) upgraded the project with awesome tasks automating the start of a Calva dev session and giving as a HUD from which we can see when we break tests and such. Wonderful. Thanks! gratitude 🙏 See updated wiki docs on, now could be the moment you should be checking what we mean when we say it is super easy to get started.

🎉 2

Can confirm - was pretty easy to add a feature. Probably an hour of setup for the env, and the pr workflow is well documented 💯

🙏 1

An hour is a lot more than expected, though. 😀 I’m not curious about the process to see if we can improve the docs and/or setup. What was your starting point? Did you have node?


Oh, I puttered around alot. An hour folds in the time it took me to find what I was looking for in the code


Awesome. Yes, I think that the effort to find the right places in the code is even more important than being at where you have compiled and running your own Calva. You found the exact right spot in the abstractions we have for providing Paredit commands. I must say at least I find Calva Paredit very pleasant to work with. (I dare say so because I can only take part credit in how this is factored and organized.)


I'm so happy you found Calva, @rayatrahman9!

💜 5
❤️ 1

Told you that we would come back about the multi cursor Paredit thing! Please consider helping with this, dear Calva friends! ❤️

bananadance 3

Can Calva automatically "Add Missing Require" on completion?


I don’t know. Can it, @UKFSJSM38 ?


Yes, when competing and the alias is already know I'm the project, clojure-lsp automatically add that require


curious - it doesn't do it for me - I have to manually 'add missing require' - I do have some that have conflicting aliases, so those I would understand, but I also can't get it to work on aliases that aren't conflicting 😕


Could you paste a simple repro snippet of how are you trying?


sure, I'll see if I can replicate on a new project quick


something like this suffice?


checking if there's any settings that might relate


Yes, will try on emacs that I know it probably should work and then on calva one sec


cool, thank you - appreciate it


Just confirmed this only works on lsp-mode(emacs) but not on Calva for some reason, probably related to how calva handles completion/resolveItem , please open a issue on Calva so we can investigate further more


ok, cool - will do


The code I tested: a.clj

(ns clojure-sample.a)

(defn foo []
(ns clojure-sample.b
   [clojure-sample.a :as my-alias]))

(ns clojure-sample.c)

my-alias ;; completion here should add the require
my-alias/foo ;; completion here should add the require


Please add this snippet to the issue if possible


Also, please provide in the issue the client<->server json logs. Check > Viewing the Logs Between the Client and Server


@U050CLJ53 you added server logs, we need client<->server json logs


Check "Viewing the Logs Between the Client and Server" on that calva link


wow, that is verbose


ah, just not handling the additionalTextEdits bit, I imagine

👍 1

I pokey'd a bit in the code to see if maybe it's just a typo - but looks like there's no mention of 'additionalTextEdits' anywhere in the code, so I suspect that would need to get built, whatever that looks like 🙈


Usually that's handled automatically by vscode language server, but I know calva overrides some things which may be related


ah, interesting


Yes, it's probably something we are missing to do in our middlware.


Could be very useful. I always assumed, foolishly, that the lack of my favorite tooling and laziness enablers was just status quo in the clj world, until working on Calva recently. I have mild lsp + vsc experience, and would be interested in pursuing this one! There goes doing my other hobbies over the next few weekends...

😂 1

That would be great, @rayatrahman9!


particularly if there's two conflicting aliases, but it could infer it based on your selection

🧵 2

Hi, what can it be that when I press Alt-Enter Calva does not evaluate the expression in the REPL but shows a menu?


Check what keyboard shortcut is bound to refactor.


That is a code action menu, probably you want ctrl-enter to eval ?


Alt+enter evaluates. But something else is also bound to the shortcut and wins. Is what I think is going on.

👍 1

Look for Quick-fix, too @U039XU7CRC4


@U0ETXRFEW: What is Quick-Fix?


Quick-fiz is the informal name of that menu


Maybe this is the problem?


How to fix this?


Only part of the problem. But, indeed, the evaluation commands are not active w/o a repl. What do you see in the jack-in terminal?


Seems to be solver somehow. I closed VSCode and restarted it. I believe it was somehow connected to giving the worng project type when starting the repl integration Either here, or there:


Some aliases will stop the nREPL server from starting. You might have gotten a cryptic warning about this. 😃


You probably still have quick-fix bound to alt+enter and it is a bit of a race condition if Calva or that will win. So I would still advice you to check that.


If you refer to this one, "cryptic" is the correct adjective:


Yes, not the best worded message ever...


@U0ETXRFEW: Where do I have to check this (I am new to VScode as well)?


What would have helped you better, @U039XU7CRC4?


How can I answer your question when I have no idea what the error message wants to tell me?


I was not even sure what to give here as an option:


It's a rather long story, unfortunately... > Calva checks the aliases and if one of them has a :main entry, then that risks replacing the main function that Calva uses. Calva's main entry starts the nREPL server that is what Calva then tries to connect to. At the same time the alias' :main entry could be startng the nREPL server properly, so the user needs to be able to choose any alias None of this tells you much since you are completely new to Clojure. But the message could end with something like TL;DR: Only choose these aliases if you know what you are doing.


The project menu is even trickier... You are assumed to know enough about the project you are starting to be able to start it, but that is of course often not the case. We can probably be a bit more careful in what we include in that menu, all options are not even relevant. But It will still be a menu where you need to know enough about to project to be able to select the right option.


If you are mainly trying to learn some Clojure. You can wait a bit with creating a project, if you like. Calva has a command for starting a Getting Started REPL. It is a guide where you use the REPL to learn the basics of Clojure, the language. See here for some info about it:


Clojure as a language or working with a REPL is not such a problem (I used to do some LISP and Racket before). Tooling is a big issue for me in Clojure I never had exposure to Java/Maven or JS/npm.


So this here does not seem to be a calva problem, but rather my lack of understanding of deps.edn (which Calva apparently reads and interprets).


The Getting Started REPL also has a Calva part, so it could be good to do at least that one so that you know a bit of what to expect from Calva.


I'll be thinking a bit about how we can help users with that deps.edn/Leiningen knowledge gap as well. It might not be a Calva problem, per se, but it is still a fact that some users will start with Calva... Thanks a lot for your feedback here!


So now after the REPL is working, what is the best way to save my file, start the build process and run the program from Calva? Ok, stupid quesiton. Just save it and it gets evaluated. But: How is this magic working? Is this Calva or Figwheel doing this?


Not a stupid question at all. If you are using Figwheel, then what happens is that Figwheel sends the file to the REPL, which *R*eads, compiles, and *E*valuates it. The result is that the app is being modified, while it is still running. It might not be magic, but it sure is wonderful.


In a regular Clojure project most often there is no process that watches files and evaluates them for you. It is instead something you do, using the evaluation commands of whatever interface you have to the REPL (Calva via nREPL in your case).


I don't think I use figwheel, but I am honestly not completely sure. about this.. 🙂


> Is this Calva or Figwheel Is why I thought you were using Figwheel. 😃 Are you using some kind of project template?


I started off with

clojure -Tclj-new app :name myname/myapp
(I replaced myname/myapp)


After I added dependencies to deps.edn, do I have to do something before I can require them in my program?


like downloading the code?


You'll need to restart the app after you have added dependencies (there are ways to load them dynamically, but let's start simpler).


Am I using figwheel or not?


I even restarted VSCode but did not solve the problem. I guess I better restart from the scratch.


Restarting VS Code is very much from scratch. You don't need to do that.


Figwheel is a ClojureScript tool. You are not using it.


As for how to run your program, it depends on what kind of program you are creating. But the development workflow is seldom to compile a program and run it. It is more often to build small parts of the program, step by step and evaluate each little piece. Here's a video that shows the workflow I use:;t=1s


Back to your project. So, you created it, and could then start it and connect the REPL, right? But after adding a dependency, you ran into problems?


I put this in the "beginners" chat: I added the following to deps.edn:

{:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.10.3"}
        instaparse/instaparse {:mvn/version "1.4.10"}}
and the following to my code
(ns odatasrv.parser
  (:require [instaparse.core :as insta]))
However, I get the following output in my REPL, even after restarting the REPL:
; Evaluating file: parser.clj
; Syntax error (FileNotFoundException) compiling at (/home/michael/Developments/Clojure/odata/parser/src/odatasrv/parser.clj:1:1).
; Could not locate instaparse/core__init.class, instaparse/core.clj or instaparse/core.cljc on classpath.
; Evaluation of file parser.clj failed: class clojure.lang.Compiler$CompilerException


What is the difference between these two things? Why would i prefer either one?

clojure -T:project/new :template app :name myname/myapp
clojure -Tclj-new app :name myname/myapp


(Yes, I know how to work with a REPL)


I'm not an expert here, but -T is a way to invoke tools. So you are invoking two different tools there. It looks like both create a project for you.


It looks right with the code you've shared. I don't understand why it doesn't work. Did you see any messages about instaparse being downloaded?


After restarting everything from the scratch it seems to work now. I think something was messed up with the path


Ah, great. If you add any more dependency, use Calva's Jack-in command again, it will restart the REPL for you.


Sorry, no it still doesn't. I am not actually sure if it was downloaded at all.


Let me try the steps you are taking and we can see what happens...



clojure -Tclj-new app :name myname/myapp


Then start VScode, open deps.edn and add the dependency:

:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.10.3"}
        instaparse/instaparse {:mvn/version "1.4.10"}}
 {:run-m {:main-opts ["-m" "odata.parser"]}
  :run-x {:ns-default odata.parser
          :exec-fn greet
          :exec-args {:name "Clojure"}}
  :build {:deps {io.github.seancorfield/build-clj
                 {:git/tag "v0.6.3" :git/sha "9b8e09b"
                  ;; since we're building an app uberjar, we do not
                  ;; need deps-deploy for  deployment:
                  :deps/root "slim"}}
          :ns-default build}
  :test {:extra-paths ["test"]
         :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"}
                      {:git/tag "v0.5.0" :git/sha "48c3c67"}}}}}


The goto my program:

(ns odata.parser
  (:require [instaparse.core :as insta]))

(defn greet
  "Callable entry point to the application."
  (println (str "Hello, " (or (:name data) "World") "!")))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (greet {:name (first args)}))

(+ 3 7)

(def as-and-bs
   "S = AB*
     AB = A B
     A = 'a'+
     B = 'b'+"))


; Evaluating file: parser.clj
; Syntax error (FileNotFoundException) compiling at (/home/michael/Developments/Clojure/parser/src/odata/parser.clj:1:1).
; Could not locate instaparse/core__init.class, instaparse/core.clj or instaparse/core.cljc on classpath.
; Evaluation of file parser.clj failed: class clojure.lang.Compiler$CompilerException
clojure.lang.Compiler/load (
odata.parser/eval5841 (NO_SOURCE_FILE:1)
clojure.lang.Compiler/eval (
clojure.core/eval (core.clj:3202)
clojure.core/eval (core.clj:3198)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.core/apply (core.clj:667)
clojure.core/with-bindings* (core.clj:1977)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.main/repl (main.clj:437)
clojure.main/repl (main.clj:458)
clojure.main/repl (main.clj:368)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:84)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:56)
nrepl.middleware.interruptible-eval/interruptible-eval (interruptible_eval.clj:152)
nrepl.middleware.session/session-exec (session.clj:218)
nrepl.middleware.session/session-exec (session.clj:217)
java.lang.Thread/run (


So it works when I do it. I can also do:

(insta/parse as-and-bs "abacus")
=> {:index 3, :reason [{:tag :string, :expecting "b"} {:tag :string, :expecting "a"}], :line 1, :column 4, :text "abacus"}


How are you evaluating the file?


I save the file with crtl-s


and i get

; Evaluating file: parser.clj
; Syntax error (FileNotFoundException) compiling at (/home/michael/Developments/Clojure/parser/src/odata/parser.clj:1:1).
; Could not locate instaparse/core__init.class, instaparse/core.clj or instaparse/core.cljc on classpath.
; Evaluation of file parser.clj failed: class clojure.lang.Compiler$CompilerException


That doesn't evaluate it, does it?


Have you enabled Evaluate on Save?


What is this? (I guess so, otherwise I wouldn't get this message in the REPL?)


Otherwise it wouldn't start evaluating the file when you save it. I recommend to not have that setting on. It's better to control the evaluation of the file and its forms yourself.


(It should work though, so I don't think it is the cause of the error.)


At the moment I am more concerned about why the dependency is not resolved....


Yes, that is very strange.


This worked:

clojure -X:run-x
Hello, Clojure!


How do I restart the repl?


Try to select no aliases when you start the REPL.


Restart the REPL by issuing the Jack-in command again.


I started it selecting no aliases

👍 1

Ok, this did the trick!


Ah. But if I start it with the :build alias, I get the same error as you get. No idea why,


I had the build alias as well


~/Projects/tests/instaparse-test(:|✔) % clojure -X:run-x         
Hello, Clojure!
~/Projects/tests/instaparse-test(:|✔) % clojure -M:build -X:run-x 
Execution error (FileNotFoundException) at (
-X:run-x (No such file or directory)

Full report at:
~/Projects/tests/instaparse-test(:|✔) % 


Hmmm, maybe that is the wrong order...

% clojure -X:run-x -M:build                      
Namespace instaparse-test.instaparse-test loaded but function not found: -M:build


But the edn has a build target:

 {:run-m {:main-opts ["-m" "odata.parser"]}
  :run-x {:ns-default odata.parser
          :exec-fn greet
          :exec-args {:name "Clojure"}}
  :build {:deps {io.github.seancorfield/build-clj
                 {:git/tag "v0.6.3" :git/sha "9b8e09b"
                  ;; since we're building an app uberjar, we do not
                  ;; need deps-deploy for  deployment:
                  :deps/root "slim"}}
          :ns-default build}
  :test {:extra-paths ["test"]


Anyway. it seems the :build alias is not meant to be used with the REPL. It is for building the app artifact.


Whatever. it works now. Thanks a lot.

👍 1

You are welcome. This was good to know for me. Lots of projects are created with that template. I have just never tried starting with the :build alias before.


Looks like you have some work to do getting that grammar in!


yes, but I probably only need part of it. I made some test with racket and grammars a while which worked quite nice. I hope Clojure is similiar good at this.


I've not used instaparse a whole lot myself, but I have heard very good things about it.


Clojure has very good interop with Java, so that is another way to get a parser, I think. (Assuming there is a parser in Java.)


I don't know Java at all, so I stick with clojure if possible.


And I hate OOP


I think usually what people do is to write a thin wrapper around any OO stuff.


Sorry, I am a compete newbie. How do I check the keyboard shortcuts for refactor?


There is a command that brings up the shortcuts editor. I don’t recall its exact name and I'm afk. But anyway, there you'll find a search field.


At a computer now. The command is Preferences: Open Keyboard Shortcuts. That brings up a view where you can search. You can search for both commands and shortcuts. Looks like so when I search alt+enter:

👍 1

Since you're a complete newbie, see here about finding commands:


Ok, I found the double key bindings and deactivated the competing extension. However, when the REPL was connected CALVA did get preference. The root cause was the missing connection to the REPL

👍 1

How do configure VS Code so I can go to Java definitions? I found this but I can't locate instructions. 🙂


Hi there Doc! This should not need so much instructions any longer. Which version of clojure-lsp are you using? The output panel Calva says should tell you that when Calva has started and clojure-lsp is done starting as well.


Thanks @U0ETXRFEW! I'm doing the hello-repl tutorial and everything works when I follow the tutorial. Except this part


When I select "Go to definition" for Math/abs I get No definition found for 'Math/abs'. So I guess that I don't have Java sources installed?


I have installed Microsoft's extensions for Java


The Java extension is probably good to have, but not used for this feature.


This doesn't work for me either. I was under the impression that it would start working now with latest clojure-lsp. Is that an incorrect expectation, @UKFSJSM38?


@U9A1RLFNV @U02EMBDU2JU @U02N27RK69K Maybe we should investigate the Java extension's API and see if it can be used for things like this?


@UGDTSFM4M I think that for now I probably should remove that in the Getting Started REPL.

👍 1

@U0ETXRFEW , I see. Thank you for looking into this!

Lukas Domagala14:04:50

Yes, there’s a lot of stuff we can do to make Java interop better, but I don’t think there’s enough usage that it’s actually a priority. Especially now that LSP can give us some of the low-hanging fruits for free with the last update


@U02EMBDU2JU except it doesn't seem to work on the example in the Getting Started Guide.


Let’s see what @UKFSJSM38 says about that. I don’t know exactly what should be working regarding Go to Def for Java sources.


I see this in the docs, though I don’t know if the info is up-to-date: > At the moment, clojure-lsp supports find definition of java classes only, methods, completion and other features are not supported yet.


find definition of java classes (not methods) are supported indeed with latest release. the JDK source is especially handled after project startup, and IIRC we are not starting properly the server on getting started, right? if so, that's the issue on Calva side More details


Ah, could be that we don't have a proper clojure-lsp in Getting Started. That was about something with clojure-lsp not liking that there is no folder, or something, wasn't it? Not sure what we can do about that on the Calva side.


yes, it's required that a correct project-root should be passed to clojure-lsp for some features work, including java support


I'll even add a log to that when no project-root-uri is passed.


What is a proper project-root?


A file path URI, which should be the project-root that is passed during initialize request of the LSP


Ah, I don't think we provide that. It's VS Code doing it. But maybe we can override it.


yes, probably


Just to give a little more context why project-root-uri is crucial: • without it we don't know the project root obviously, without that we can't get the classpath/source-paths, not being able to know what scan with clj-kondo • Without analysis we don't have most features, especially java which completely relies on clj-kondo analysis


Can I see what project root is sent somehow? (serverInfo crashes w/o project root.)


Or w/o I don't know. But whatever is sent is problematic at least. 😃


yes, this should be on the client<->json logs


project-root-uri under initialize request that Calva send


Hmm, I don't think we have a json log for that. Is it something clojure-lsp creates?


yes you have, vscode-language-client creates that output channel Check "Viewing the Logs Between the Client and Server"


Ah, verbose. Thanks!


You mean that

"rootUri": null,
Doesn't work, right? 😃


Yeah, I thought it was project-root-uri but you are right, it's that rootUri indeed


Even if there is no project open calva coud create a empty deps.edn in a tmp folder, would be probably enough


But I guess when user see the getting started, it already opened a clojure buffer somewhere?


The getting started files are opened in a filesystem folder. But we can't programmatically tell VS Code to open it, so we open the files. VS Code then either sends null because it has no workspaceFolder or some unrelated workspaceFolder if that is opened when the getting started repl is started. I'm trying to see if we can send something explicitly, but I only find a workspaceFolder field... Maybe we can send an alternative Uri via the init options? That would override any rootUri. Hackish... Maybe I should be looking a bit more before we resort to such things.


We are in a better place now at least, because I had not understood this about we needing to send a rootUri. 😃

👍 1

yeah, I'd like to keep following the spec, if that is not possible for calva, probably something to improve on vscode-language-client side


I think we can make this work. Here's hacking in just /tmp as the folder:

workspaceFolder: {
      uri: vscode.Uri.file('/tmp/'),
      name: 'foo',
      index: 0,


Nice :) A empty {} deps.edn on that tmp folder may help making even more features work


also, maybe use a more specific folder than /tmp ? having /tmp/getting-started/.lsp and /tmp/getting-startged/.clj-kondo sounds a little bit better for organization 🤷


Yes, I have created the files so I know exactly where they are, in places like

This was just a test. And it also seems clojure-lsp doesn't need to crash on rootUri: null if it could fall back on some arbitrary temp dir, and complain in some way about the lack of rootUri.


it does not crash, only some features are not available, and I added today the log about missing rootUri


It looks like a crash in the errors I get when trying things like serverInfo:

Starting clojure-lsp at /Users/pez/Projects/calva/clojure-lsp
clojure/serverInfo/raw failed: Error: Internal error.
    at handleResponse (/Users/pez/Projects/calva/node_modules/vscode-jsonrpc/lib/common/connection.js:477:48)
    at processMessageQueue (/Users/pez/Projects/calva/node_modules/vscode-jsonrpc/lib/common/connection.js:292:17)
    at Immediate.<anonymous> (/Users/pez/Projects/calva/node_modules/vscode-jsonrpc/lib/common/connection.js:276:13)
    at processImmediate (/Users/pez/Projects/calva/lib/internal/timers.js:464:21)
    at process.callbackTrampoline (node:internal/async_hooks:130:17) {code: -32603, data: 'java.lang.RuntimeException: java.lang.reflect.…r.serverInfoRaw(server.clj:135)
	... 15 more
', vslsStack: Array(5), stack: 'Error: Internal error.
    at handleResponse …Trampoline (node:internal/async_hooks:130:17)', message: 'Internal error.'}


serverInfo/raw is one of the things does not work, but probably we can make it work with the basic, even so server starts properly


As far as Calva concerns it is not important. We will be sending something non-null for rootUri. 😃

👍 1

> yeah, I’d like to keep following the spec, if that is not possible for calva, probably something to improve on vscode-language-client side We should always be able to follow the spec, for the most part. Seeing that VSCode, the vscode-language-client lib, and the Language Server Protocol itself are all maintained by Microsoft, I expect to have a first-class experience with protocol support.

☝️ 1

100% agree @U9A1RLFNV, even so to be honest, I already saw one or other thing that is not possible on vscode-language-server but possible for emacs :man-shrugging:


Pretty rare tho


The percentage during server initialization is one example, that is present on lsp-mode emacs following spec, but not on vscode


So, the library may lag behind the protocol in terms of support.


Yeah, that's what I think, kind of odd indeed, maybe open issues there would be a good start


I'm all for following protocol. Until it stops something from working. Then I am all for breaking protocol. 😃

Lukas Domagala10:04:18

I think there’s never really a need to “break” the protocol. If some call doesn’t do what we need it to do, we can always extend the protocol with new calls without making it incompatible.


The issue is that this one is a critical required LSP method for whole thing work, initialize request, I wouldn't like to create clojure/initialize request 😛


I have java installed on my Mac already

🧵 3