cursive

nnecklace 2025-04-10T12:01:03.350399Z

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?

2food 2025-04-10T12:23:23.792949Z

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)

ericdallo 2025-04-10T12:31:10.468899Z

Under the hood clojure-lsp calls organize imports internally after adding the require/import, that's why it sorts

👍 1
nnecklace 2025-04-10T12:43:27.789269Z

Thanks @tormathi ! I'll tell my colleague about this

😊 1
henrik 2025-04-10T17:04:49.682239Z

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?

ericdallo 2025-04-10T14:03:13.989369Z

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)

ericdallo 2025-04-11T11:54:47.554539Z

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

ericdallo 2025-04-11T11:55:08.913539Z

Interesting, any reason why? all other editor clients do that

ericdallo 2025-04-11T14:10:53.123949Z

Interesting, when running with lein, I can see cursive sends the clone op

cfleming 2025-04-11T22:12:41.256039Z

That's because Cursive just delegates to lein repl in that case, and I suspect that's lein doing it under the hood.

cfleming 2025-04-11T22:16:23.407079Z

Ah, wait - Cursive uses nrepl/new-session, and that uses clone under the hood. But I'm using an old nrepl version.

cfleming 2025-04-11T22:46:46.595659Z

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.

ericdallo 2025-04-10T14:03:46.656989Z

it's basically add client-name "Cursive" and client-version "..." to the clone op

cfleming 2025-04-11T01:09:26.121429Z

I'm curious, why do you want to know which client is connecting?

cfleming 2025-04-11T02:09:39.067369Z

Either way, I just checked and Cursive never actually uses the clone op anyway.

ericdallo 2025-04-13T13:10:32.638059Z

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?

cfleming 2025-04-13T20:40:26.990349Z

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.

onetom 2025-04-14T05:24:15.498649Z

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.

👍 1
bocaj 2025-04-10T18:14:52.608949Z

I'm running into this error in IntelliJ on Windows 11 "Illegal char <:> at index 2:"

bocaj 2025-04-10T18:18:59.763149Z

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)

bocaj 2025-04-10T18:23:39.617679Z

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

bocaj 2025-04-10T18:24:34.594739Z

Intellij is 2024.3.5

bocaj 2025-04-10T20:35:49.382859Z

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.

bocaj 2025-04-10T21:00:23.897829Z

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.

cfleming 2025-04-11T01:12:56.852499Z

Pretty sure that's IntelliJ, I construct the command line but then IntelliJ pieces it together.