Trying to start ClojureScript nREPL with CLI Tools
sbondaryev opened this issue · 4 comments
Hello
I am trying to start ClojureScript nREPL with CLI Tools
When I try to send ClojureScript expression to ClojureScropt nREPL it is treaded as Clojure
deps.edn
{:deps {
org.clojure/clojure {:mvn/version "1.9.0"}
org.clojure/clojurescript {:mvn/version "1.10.339"}
nrepl {:mvn/version "0.3.1"}
cider/piggieback {:mvn/version "0.3.6"}
}}
Start nREPL
user=> (require '[clojure.tools.nrepl.server :as server])
nil
user=> (require '[cider.piggieback :as pback])
nil
user=> (server/start-server :handler (server/default-handler #'pback/wrap-cljs-repl) :port 7888)
#clojure.tools.nrepl.server.Server{:server-socket #object[java.net.ServerSocket 0x70c205bf "ServerSocket[addr=/0:0:0:0:0:0:0:0,localport=7888]"], :port 7888, :open-transports #object[clojure.lang.Atom 0x46894dc5 {:status :ready, :val #{}}], :transport #object[clojure.tools.nrepl.transport$bencode 0x596afb2f "clojure.tools.nrepl.transport$bencode@596afb2f"], :greeting nil, :handler #object[clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877 0x79ba0285 "clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877@79ba0285"], :ss #object[java.net.ServerSocket 0x70c205bf "ServerSocket[addr=/0:0:0:0:0:0:0:0,localport=7888]"]}
Define a function to send message to nREPL
user=> (require '[clojure.tools.nrepl])
nil
user=> (defn msg [port code]
(with-open [conn (clojure.tools.nrepl/connect :port port)]
(-> (clojure.tools.nrepl/client conn 20000)
(clojure.tools.nrepl/message {:op :eval :code code})
doall
pprint)))
#'user/msg
Try to switch to ClojureScript nREPL
user=> (msg 7888 "(require 'cljs.repl.nashorn)")
({:id "77d64088-aa65-4936-a14d-f10c4dff2244",
:ns "user",
:session "f0184538-0508-4850-9dca-37aea3773ade",
:value "nil"}
{:id "77d64088-aa65-4936-a14d-f10c4dff2244",
:session "f0184538-0508-4850-9dca-37aea3773ade",
:status ["done"]})
nil
user=> (msg 7888 "(cider.piggieback/cljs-repl (cljs.repl.nashorn/repl-env))")
({:id "21b36257-3d36-4b6a-a9c5-cfb8543dabb2",
:out "To quit, type: :cljs/quit\n", <<- It seems to be OK
:session "10bfc16d-44d9-44f7-a6f9-94a870661e74"}
{:id "21b36257-3d36-4b6a-a9c5-cfb8543dabb2",
:ns "cljs.user",
:session "10bfc16d-44d9-44f7-a6f9-94a870661e74",
:value "nil"}
{:id "21b36257-3d36-4b6a-a9c5-cfb8543dabb2",
:session "10bfc16d-44d9-44f7-a6f9-94a870661e74",
:status ["done"]})
nil
Check if ClojureScript nREPL works
user=> (msg 7888 "(clj->js {})")
({:ex "class clojure.lang.Compiler$CompilerException",
:id "86184aa4-b1a1-4e01-86f7-57fc458dbdee",
:root-ex "class clojure.lang.Compiler$CompilerException",
:session "fa1628e3-ff34-4190-96f4-df600f8a36db",
:status ["eval-error"]}
{:err
"CompilerException java.lang.RuntimeException: Unable to resolve symbol: clj->js in this context, compiling:(null:1:1) \n",
:id "86184aa4-b1a1-4e01-86f7-57fc458dbdee",
:session "fa1628e3-ff34-4190-96f4-df600f8a36db"}
{:id "86184aa4-b1a1-4e01-86f7-57fc458dbdee",
:session "fa1628e3-ff34-4190-96f4-df600f8a36db",
:status ["done"]})
So if you look at the responses and take note of the :session
key value. Notice how they are all different. In this case you can think of this as sending operations to different REPLs.
If you want to talk to the cljs repl you will have to talk to that session.
This easiest way to get a stable session is to take the client and make a session client out of it.
Then when you send your messages to that client they are all going "to the same repl" (actually
you are speaking to different threads with isolated bindings).
(def conn (nrepl/connect :port 7888))
(def client (nrepl/client conn 1000))
(def sess1 (nrepl/client-session client))
(def sess2 (nrepl/client-session client))
;; now you will send things to the different sessions and you will notice the session id stays stable
(nrepl/message sess1 {:op :eval :code "(list 1 2 3)"})
(nrepl/message sess2 {:op :eval :code "(list 1 2 3)"})
And you will need to make a cljs-session for your cljs-repl. But what you have done above should work for vscode calva as you have separate sessions and one is a cljs session.
Great! Thanks @bhauman
Just to make the things done - here are modified steps
Define a function to send message to nREPL
user=> (require '[clojure.tools.nrepl])
nil
user=> (defn create-messenger [port]
(let [session (-> (clojure.tools.nrepl/connect :port port)
(clojure.tools.nrepl/client 20000)
(clojure.tools.nrepl/client-session))]
#(-> (clojure.tools.nrepl/message session {:op :eval :code %})
doall
pprint)))
#'user/create-messenger
user=> (def msg (create-messenger 7888))
#'user/msg
Switch to ClojureScript nREPL
user=> (msg "(require 'cljs.repl.nashorn)")
({:id "5d92a255-9e2b-42f9-b0c8-6e8232850a61",
:ns "user",
:session "3f732512-7af4-4f56-b43f-054b1eb246b4",
:value "nil"}
{:id "5d92a255-9e2b-42f9-b0c8-6e8232850a61",
:session "3f732512-7af4-4f56-b43f-054b1eb246b4",
:status ["done"]})
nil
user=> (msg "(cider.piggieback/cljs-repl (cljs.repl.nashorn/repl-env))")
({:id "cd73345e-7078-4249-ae37-1fe2cba61be0",
:out "To quit, type: :cljs/quit\n", <<- It is OK
:session "3f732512-7af4-4f56-b43f-054b1eb246b4"}
{:id "cd73345e-7078-4249-ae37-1fe2cba61be0",
:ns "cljs.user",
:session "3f732512-7af4-4f56-b43f-054b1eb246b4",
:value "nil"}
{:id "cd73345e-7078-4249-ae37-1fe2cba61be0",
:session "3f732512-7af4-4f56-b43f-054b1eb246b4",
:status ["done"]})
nil
Evaluate ClojureScript
user=> (msg "(clj->js {})")
({:id "561211b9-ae5f-4674-86ce-f2e1a7141bc0",
:ns "cljs.user",
:session "3f732512-7af4-4f56-b43f-054b1eb246b4",
:value "#js {}"} <<- It works now
{:id "561211b9-ae5f-4674-86ce-f2e1a7141bc0",
:session "3f732512-7af4-4f56-b43f-054b1eb246b4",
:status ["done"]})
nil
Indeed the session ID remains the same 3f732512-7af4-4f56-b43f-054b1eb246b4
Let's close this as it seems answered.