nrepl

https://github.com/nrepl/nrepl || https://nrepl.org
cfleming 2019-10-14T06:51:28.007500Z

I’m having a problem implementing support for nrepl.edn in Cursive, although I’m not sure if this is an nREPL problem or a piggieback one.

cfleming 2019-10-14T06:52:08.008100Z

I thought I had implemented the support, but when I try to test piggieback, I get:

Connecting to local nREPL server...
nREPL server started on port 52466 on host 127.0.0.1
Clojure 1.10.1
(require 'cljs.repl.nashorn 'cider.piggieback)
=> nil
(cider.piggieback/cljs-repl (cljs.repl.nashorn/repl-env))
Execution error (IllegalStateException) at cider.piggieback/cljs-repl (piggieback_impl.clj:168).
Can't change/establish root binding of: *cljs-repl-env* with set

cfleming 2019-10-14T06:52:45.008800Z

I found a couple of issues about this, but they were either about using very old versions of various things, or about using trampoline with leiningen.

cfleming 2019-10-14T06:53:40.009200Z

I’m establishing my server like this:

`(do
   (-> (File. ~(.getCanonicalPath init-file))
       (.deleteOnExit))
   (try (require 'nrepl.server 'nrepl.config 'nrepl.cmdline)
        (catch Throwable t#
          (println "Error loading nrepl.server:"
                   (or (.getMessage t#) (type t#)))))
   (try
     (let [config# (merge {:host "127.0.0.1"
                           :port 0}
                          nrepl.config/config)
           {:keys [port# bind# handler# transport# greeting#]} (nrepl.cmdline/server-opts config#)
           server# (nrepl.server/start-server
                     :port port#
                     :bind bind#
                     :ack-port ~ack-port
                     :handler handler#
                     :transport-fn transport#
                     :greeting-fn greeting#)
           port# (:port server#)]
       (println "nREPL server started on port" port# "on host 127.0.0.1"))
     (catch Throwable t#
       (println "Error starting server:"
                (or (.getMessage t#) (type t#))))))

cfleming 2019-10-14T06:54:07.009500Z

deps.edn:

{:deps    {org.clojure/clojurescript {:mvn/version "1.10.520"}}
 :aliases {:repl {:extra-deps {nrepl/nrepl {:mvn/version "0.6.0"}
                               cider/piggieback {:mvn/version "0.4.2"}}}}}

cfleming 2019-10-14T06:54:28.009800Z

nrepl.edn:

{:middleware [cider.piggieback/wrap-cljs-repl]}

cfleming 2019-10-14T06:55:30.010700Z

I’m not directly invoking nrepl.cmdline for everything, but I am reusing most of its logic, in particular for creating the handler from the configured middleware.

cfleming 2019-10-14T06:55:37.010900Z

Am I missing something obvious?

cfleming 2019-10-14T07:37:34.011800Z

Ok, one problem was that nrepl.edn should have been .nrepl.edn, so the middleware wasn’t being found. However even after fixing that I’m still having the same problem.

cfleming 2019-10-14T07:44:58.012500Z

I’ve debugged this, and the piggieback middleware does seem to be being applied to the handler correctly, which means I’m pretty much out of ideas.

bozhidar 2019-10-14T07:48:05.012900Z

Hmm, if the handler is correct I can’t imagine how this wouldn’t work.

cfleming 2019-10-14T07:49:39.014Z

I’m going to try just calling nrepl.cmdline directly and passing the args as if I were calling -main, and see if I’m missing something subtle.

bozhidar 2019-10-14T07:49:46.014200Z

Did you try it with some other middleware as well?

cfleming 2019-10-14T07:49:58.014500Z

No, is there an easy one to test with?

cfleming 2019-10-14T07:50:17.014800Z

Is there an echo middleware or something like that?

bozhidar 2019-10-14T07:51:17.015700Z

There’s not, but I guess it’s not a bad idea. 🙂 There a few pretty basic ops in cider-nrepl, though - e.g. classpath.

cfleming 2019-10-14T07:51:39.016100Z

The problem is I don’t have anything in the client for sending custom messages.

cfleming 2019-10-14T07:51:58.016700Z

I’m going to try calling nrepl.cmdline first, which is an easy test.

bozhidar 2019-10-14T07:52:07.016900Z

Oh, got it. I always assumed you had some generic support for custom messages.

bozhidar 2019-10-14T07:52:12.017100Z

:thumbsup:

cfleming 2019-10-14T07:52:29.017400Z

I don’t really use custom messages at all, so I’ve never had the need.

cfleming 2019-10-14T08:06:23.017800Z

Ok, so if I just call nrepl.cmdline directly, that works.

cfleming 2019-10-14T08:06:44.018200Z

So I’m obviously missing something either subtle or obvious.

cfleming 2019-10-14T08:07:45.019Z

I think I’ll just keep doing that so that Cursive will interop better with all the related nREPL tooling, and things like .nrepl.port should just work.

cfleming 2019-10-14T08:08:12.019400Z

It would be nice to be able to hide the port ack message.

bozhidar 2019-10-14T08:12:04.019500Z

I agree. I’d also welcome some feedback on the current state of the nrepl.cmdline API, which I consider experimental at this point. Obviously without having clients of it around it was hard to assess if we got it right or not. 🙂

bozhidar 2019-10-14T08:12:20.019700Z

Can you file a ticket about this?

cfleming 2019-10-14T08:13:00.019900Z

This is currently the extent of my use of it:

(try (require 'nrepl.cmdline)
               (catch Throwable t#
                 (println "Error loading nREPL:"
                          (or (.getMessage t#) (type t#)))
                 (System/exit 1)))
          (nrepl.cmdline/-main "--ack" ~(str ack-port))

cfleming 2019-10-14T08:13:03.020100Z

🙂

bozhidar 2019-10-14T08:13:06.020300Z

That definitely surprised me, as your code looked legit to me, but I’m glad to hear we didn’t break something. 😄

bozhidar 2019-10-14T08:13:36.020500Z

Ah, got it. I thought you went more granular than that. 😄

bozhidar 2019-10-14T08:14:28.020700Z

One bit of feedback I see is that maybe we should suppress exceptions coming from -main.

cfleming 2019-10-14T08:18:59.020900Z

https://github.com/nrepl/nrepl/issues/167

cfleming 2019-10-14T08:20:18.021200Z

Yeah, it’s weird. I think I’ll continue just calling that directly, but it’s definitely odd.