Noticed something interesting today with my colleague who uses cursive. I use emacs and clojure-lsp, and I usually add missing libs/requires with add-missing-libspec
, which not only adds missing libs but also sorts the :require in alphabetical order and adds a linebreak after :require . (Naturally vscode with clojure-lsp does this as well).
Example of what it would look like after adding clojure.string (if it were missing).
(ns foo.bar
(:require
[ :as io]
[clojure.string :as string]
[clojure.test :refer :all]))
However, cursive seems to only append the missing lib to the list and doesn't necessarily add a newline after :require or perform any sorting
Example result of how the same procedure would look like in cursive
(ns foo.bar
(:require [ :as io]
[clojure.test :refer :all]
[clojure.string :as string]))
Is there a way to make cursive's add import/require feature format and sort the namespace's :require like clojure-lsp?There is an action called "Optimize Imports" as well as some options to do this on save and on auto import. (if you search for "optimize import" in the settings you'll see where they are)
Under the hood clojure-lsp calls organize imports internally after adding the require/import, that's why it sorts
Sorry to butt in, but while Cursive’s orgnize imports works well for the most time, it doesn’t necessarily do well with CLJC files. Is clojure-lsp better in this regard?
Hey @cfleming, from https://clojurians.slack.com/archives/C17JYSA3H/p1744123473420459, we added 2 new fields to the clone nrepl op to give info about the client being used, would you consider adding that to cursive? that would help understanding who is the nrepl client, I already opened PRs on all other editor plugins (calva, emacs, vim)
I'm working on a nrepl middleware to help with analysis about REPL usage, and one of them is which client spawned or connected to the repl session
Interesting, any reason why? all other editor clients do that
Interesting, when running with lein, I can see cursive sends the clone op
That's because Cursive just delegates to lein repl in that case, and I suspect that's lein doing it under the hood.
Ah, wait - Cursive uses nrepl/new-session, and that uses clone under the hood. But I'm using an old nrepl version.
There also doesn't seem to be any way to pass additional fields to clone via new-session, at least with the version I'm using.
it's basically add client-name "Cursive" and client-version "..." to the clone op
I'm curious, why do you want to know which client is connecting?
Either way, I just checked and Cursive never actually uses the clone op anyway.
Indeed, I opened a PR https://github.com/nrepl/nrepl/pull/371 adding that support for new-session, BTW how old is the nrepl version and do you intend to bump that soon?
The version I use is ancient, 0.8.3. I didn't have plans to bump it, since Cursive only really uses eval and load-file, and those work fine.
we are getting some middleware initialization errors too when connecting to our own nrepl server (which we start on a datomic cloud ion server).
i can imagine the old nrepl client might be the culprit.
we would also like to get some insights to our repl usage.
mainly for audit purposes, since we allow access to our prod machines, so we can efficiently test some of our upcoming datomic queries or we can hotfix production issues before we roll them out more safely via the CI pipeline.
ideally we would like the server to know who is the connecting human, so we could even automatically annotate the datomic transactions they make via the repl.
I'm running into this error in IntelliJ on Windows 11 "Illegal char <:> at index 2:"
I'm running into this error while running a repl
2025-04-10 11:10:41,998 [ 125906] INFO - #c.i.e.r.ExecutionUtil - Error running 'REPL':<br>Illegal char <:> at index 2: @C:\Users\jacob\AppData\Local\Temp\file_arg15981024336324364157.txt
java.nio.file.InvalidPathException: Illegal char <:> at index 2: @C:\Users\jacob\AppData\Local\Temp\file_arg15981024336324364157.txt
at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:199)
at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:175)
at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:231)
at com.intellij.platform.core.nio.fs.DelegatingFileSystem.getPath(DelegatingFileSystem.java:96)
at java.base/java.nio.file.Path.of(Path.java:148)
at java.base/java.nio.file.Paths.get(Paths.java:69)
at com.intellij.openapi.projectRoots.JdkCommandLineSetup.requestUploadIntoTarget(JdkCommandLineSetup.kt:90)
at com.intellij.openapi.projectRoots.JdkCommandLineSetup.requestUploadIntoTarget$default(JdkCommandLineSetup.kt:85)
at com.intellij.openapi.projectRoots.JdkCommandLineSetup.getClassPathValues(JdkCommandLineSetup.kt:692)
at com.intellij.openapi.projectRoots.JdkCommandLineSetup.composeClassPathValues(JdkCommandLineSetup.kt:680)
at com.intellij.openapi.projectRoots.JdkCommandLineSetup.appendParamsEncodingClasspath(JdkCommandLineSetup.kt:673)
at com.intellij.openapi.projectRoots.JdkCommandLineSetup.setupClasspathAndParameters(JdkCommandLineSetup.kt:295)
at com.intellij.openapi.projectRoots.JdkCommandLineSetup.setupCommandLine(JdkCommandLineSetup.kt:211)
at com.intellij.openapi.projectRoots.JdkUtil.setupJVMCommandLine(JdkUtil.java:125)
at com.intellij.openapi.projectRoots.JdkUtil.setupJVMCommandLine(JdkUtil.java:131)
at com.intellij.execution.configurations.SimpleJavaParameters.toCommandLine(SimpleJavaParameters.java:204)
at cursive.repl.process_runner$execute.invokeStatic(process_runner.clj:244)
at cursive.repl.process_runner$execute.invoke(process_runner.clj:243)
at clojure.lang.Var.invoke(Var.java:408)
at cursive.api.DelayedFn.invoke(DelayedFn.java:51)
at cursive.repl.runner.LocalConfiguration$getRunProfileState$2.execute(LocalReplRunConfigurations.kt:134)
at com.intellij.execution.impl.DefaultJavaProgramRunner.executeJavaState(DefaultJavaProgramRunner.java:188)
at com.intellij.execution.impl.DefaultJavaProgramRunner.doExecute(DefaultJavaProgramRunner.java:135)
at com.intellij.execution.impl.DefaultJavaProgramRunner.lambda$execute$2(DefaultJavaProgramRunner.java:114)
at com.intellij.execution.ExecutionManager.startRunProfile$lambda$0(ExecutionManager.kt:74)
at com.intellij.execution.impl.ExecutionManagerImpl.startRunProfile$lambda$5(ExecutionManagerImpl.kt:228)
at com.intellij.execution.impl.ExecutionManagerImpl$doStartRunProfile$$inlined$Runnable$1.run(Runnable.kt:30)
at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:236)
at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:25)
at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:198)
at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread$lambda$2(AnyThreadWriteThreadingSupport.kt:217)
at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:128)
at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread(AnyThreadWriteThreadingSupport.kt:216)
at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:843)
at com.intellij.openapi.application.impl.ApplicationImpl$2.run(ApplicationImpl.java:421)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:103)
at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:103)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:109)
at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:103)
at com.intellij.util.concurrency.ContextRunnable.run(ContextRunnable.java:27)
at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:117)
at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:43)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:781)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:728)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:750)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:675)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:573)
at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18$lambda$17$lambda$16$lambda$15(IdeEventQueue.kt:355)
at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:857)
at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18$lambda$17$lambda$16(IdeEventQueue.kt:354)
at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$2$lambda$1(IdeEventQueue.kt:1045)
at com.intellij.openapi.application.WriteIntentReadAction.lambda$run$0(WriteIntentReadAction.java:24)
at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:128)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteIntentReadAction(ApplicationImpl.java:917)
at com.intellij.openapi.application.WriteIntentReadAction.compute(WriteIntentReadAction.java:55)
at com.intellij.openapi.application.WriteIntentReadAction.run(WriteIntentReadAction.java:23)
at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$2(IdeEventQueue.kt:1045)
at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$3(IdeEventQueue.kt:1054)
at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:109)
at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1054)
at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18(IdeEventQueue.kt:349)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:395)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
deps.clj is the latest
PS C:\Users\jacob> ls C:\Users\jacob\.deps.clj\1.12.0.1530\ClojureTools\
Directory: C:\Users\jacob\.deps.clj\1.12.0.1530\ClojureTools
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/10/2025 11:16 AM 17226431 clojure-tools-1.12.0.1530.jar
-a---- 4/10/2025 11:19 AM 477 deps.edn
-a---- 4/10/2025 11:16 AM 59 example-deps.edn
-a---- 4/10/2025 11:16 AM 4067 exec.jar
-a---- 4/10/2025 11:16 AM 126 tools.ednIntellij is 2024.3.5
I invalidated all caches and created a new run configuration and chose to shorten command with Jar Manifest. The new configuration works however the old configuration cannot be updated to use shorten command line Jar Manifest.
Nevermind; only the IntelliJ built classpath is working out. This is clearly a windows issue, but I'm curious if Cursive is building the command or intellij.
Pretty sure that's IntelliJ, I construct the command line but then IntelliJ pieces it together.