Skip to content

Commit 6d6d2f5

Browse files
committed
Add basic NREPL support (for fun)
1 parent 3902004 commit 6d6d2f5

File tree

8 files changed

+126
-18
lines changed

8 files changed

+126
-18
lines changed

plugin/socketrepl.vim

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,25 @@ function! StartIfNotRunning()
1515
endfunction
1616
command! Start call StartIfNotRunning()
1717

18-
function! Connect(host_colon_port)
18+
function! Connect(host_colon_port, op_code)
1919
if a:host_colon_port == ""
2020
let conn = "localhost:5555"
2121
else
2222
let conn = a:host_colon_port
2323
endif
24-
let res = rpcnotify(g:nvim_tcp_plugin_channel, 'connect', conn)
24+
let res = rpcnotify(g:nvim_tcp_plugin_channel, a:op_code, conn)
2525
return res
2626
endfunction
2727

28-
function! ReadyConnect(host_colon_port)
28+
function! ReadyConnect(host_colon_port, op_code)
2929
if g:socket_repl_plugin_ready == 1
30-
call Connect(a:host_colon_port)
30+
call Connect(a:host_colon_port, a:op_code)
3131
else
3232
echo s:not_ready
3333
endif
3434
endfunction
35-
command! -nargs=? Connect call ReadyConnect("<args>")
35+
command! -nargs=? Connect call ReadyConnect("<args>", "connect")
36+
command! -nargs=? NConnect call ReadyConnect("<args>", "connect-nrepl")
3637

3738
function! EvalBuffer()
3839
ReplLog

plugin/socketrepl.vim.debug

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
let g:nvim_tcp_plugin_channel = 0
2+
let g:manually_start_socket_repl_plugin = 1
23

3-
function! Connect(host_colon_port)
4+
function! Connect(host_colon_port, op_code)
45
if a:host_colon_port == ""
56
let conn = "localhost:5555"
67
else
78
let conn = a:host_colon_port
89
endif
9-
let res = rpcrequest(g:nvim_tcp_plugin_channel, 'connect', conn)
10+
let res = rpcrequest(g:nvim_tcp_plugin_channel, a:op_code, conn)
1011
return res
1112
endfunction
12-
command! -nargs=? Connect call Connect("<args>")
13+
command! -nargs=? Connect call Connect("<args>", "connect")
14+
command! -nargs=? NConnect call Connect("<args>", "connect-nrepl")
1315

1416
function! EvalBuffer()
1517
ReplLog

project.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
:dependencies [[org.clojure/clojure "1.9.0-alpha12"]
77
[org.clojure/tools.logging "0.3.1"]
88
[org.clojure/tools.namespace "0.2.11"]
9+
[org.clojure/tools.nrepl "0.2.12"]
910
[log4j/log4j "1.2.17" :exclusions [javax.mail/mail
1011
javax.jms/jms
1112
com.sun.jmdk/jmxtools
44.6 KB
Binary file not shown.

src/socket_repl/nrepl.clj

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
(ns socket-repl.nrepl
2+
"Provides a channel interface to nrepl input and output."
3+
(:require
4+
[clojure.java.io :as io]
5+
[clojure.core.async :as async]
6+
[clojure.tools.nrepl :as nrepl]
7+
[socket-repl.util :refer [log-start log-stop]]))
8+
9+
(defn subscribe-output
10+
"Pipes the nrepl output to `chan`"
11+
[{:keys [output-channel]} chan]
12+
(async/pipe output-channel chan))
13+
14+
(defn connect
15+
"Create a connection to a nrepl."
16+
[{:keys [connection]} host port]
17+
(let [port (Integer/parseInt port)]
18+
(reset! connection {:host host
19+
:port port
20+
:connection (nrepl/connect :port port)})))
21+
22+
(defn output-channel
23+
[nrepl]
24+
(:output-channel nrepl))
25+
26+
(defn input-channel
27+
[nrepl]
28+
(:input-channel nrepl))
29+
30+
(defn client
31+
[nrepl]
32+
(-> nrepl
33+
:connection
34+
deref
35+
:connection
36+
(nrepl/client 1000)))
37+
38+
(defn connected?
39+
[{:keys [connection]}]
40+
(:host @connection))
41+
42+
(defn start
43+
[{:keys [input-channel output-channel] :as nrepl}]
44+
(log-start
45+
"nrepl"
46+
(async/thread
47+
(loop []
48+
(when-let [input (async/<!! input-channel)]
49+
(when (connected? nrepl)
50+
(async/onto-chan
51+
output-channel
52+
(nrepl/response-values
53+
(nrepl/message (client nrepl)
54+
{:op "eval" :code (pr-str input)}))
55+
false))
56+
(recur))))
57+
nrepl))
58+
59+
(defn stop
60+
[{:keys [connection output-channel input-channel] :as nrepl}]
61+
(log-stop
62+
"nrepl"
63+
(.close (:connection @connection))
64+
(async/close! output-channel)
65+
(async/close! input-channel)
66+
nrepl))
67+
68+
(defn new
69+
[]
70+
{:input-channel (async/chan 1024)
71+
:output-channel (async/chan 1024)
72+
:connection (atom {:host nil
73+
:port nil
74+
:connection nil})})

src/socket_repl/repl_log.clj

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"Writes (presumably socket output) to the repl log."
33
(:require
44
[clojure.core.async :as async]
5+
[socket-repl.nrepl :as nrepl]
56
[socket-repl.socket-repl :as socket-repl]
67
[socket-repl.util :refer [log-start log-stop]])
78
(:import
@@ -18,13 +19,16 @@
1819
(:input-channel repl-log))
1920

2021
(defn start
21-
[{:keys [file input-channel socket-repl] :as repl-log}]
22+
[{:keys [file input-channel socket-repl nrepl] :as repl-log}]
2223

2324
(log-start
2425
"repl-log"
2526
;; Subscribe to socket-repl output.
2627
(socket-repl/subscribe-output socket-repl input-channel)
2728

29+
;; Subscribe to nrepl output.
30+
(nrepl/subscribe-output nrepl input-channel)
31+
2832
;; Write input to file.
2933
(let [print-stream (PrintStream. file)]
3034
(async/thread
@@ -44,8 +48,9 @@
4448
(dissoc repl-log :print-stream :input-channel)))
4549

4650
(defn new
47-
[socket-repl]
51+
[socket-repl nrepl]
4852
{:socket-repl socket-repl
53+
:nrepl nrepl
4954
:file (File/createTempFile "socket-repl" ".txt")
5055
:print-stream nil
5156
:input-channel (async/chan 1024)})

src/socket_repl/socket_repl_plugin.clj

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
[clojure.tools.logging :as log]
99
[neovim-client.message :as message]
1010
[neovim-client.nvim :as nvim]
11+
[socket-repl.nrepl :as nrepl]
1112
[socket-repl.repl-log :as repl-log]
1213
[socket-repl.socket-repl :as socket-repl]
1314
[socket-repl.util :refer [log-start log-stop]]))
@@ -43,9 +44,10 @@
4344
\n"######################\n")))
4445

4546
(defn run-command
46-
[{:keys [nvim socket-repl]} f]
47+
[{:keys [nvim nrepl socket-repl]} f]
4748
(fn [msg]
48-
(if-not (socket-repl/connected? socket-repl)
49+
(if-not (or (socket-repl/connected? socket-repl)
50+
(nrepl/connected? nrepl))
4951
(async/thread
5052
(nvim/vim-command
5153
nvim ":echo 'Use :Connect host:port to connect to a socket repl'"))
@@ -77,14 +79,15 @@
7779
(:code-channel plugin))
7880

7981
(defn start
80-
[{:keys [nvim repl-log socket-repl code-channel] :as plugin}]
82+
[{:keys [nvim nrepl repl-log socket-repl code-channel] :as plugin}]
8183

8284
;; Wire sub-component io.
8385
(log-start
8486
"plugin"
8587
(let [mult (async/mult code-channel)]
8688
(async/tap mult (socket-repl/input-channel socket-repl))
87-
(async/tap mult (repl-log/input-channel repl-log)))
89+
(async/tap mult (repl-log/input-channel repl-log))
90+
(async/tap mult (nrepl/input-channel nrepl)))
8891

8992
;; Setup plugin functions.
9093
(nvim/register-method!
@@ -104,6 +107,24 @@
104107
":echo 'Unable to connect to socket repl.'"))))
105108
:done)))
106109

110+
(nvim/register-method!
111+
nvim
112+
"connect-nrepl"
113+
(fn [msg]
114+
;; TODO - reuse this
115+
(let [[host port] (-> msg
116+
message/params
117+
first
118+
(string/split #":"))]
119+
(try
120+
(nrepl/connect nrepl host port)
121+
(catch Throwable t
122+
(log/error t "Error connecting to nrepl")
123+
(async/thread (nvim/vim-command
124+
nvim
125+
":echo 'Unable to connect to nrepl.'"))))
126+
:done)))
127+
107128
(nvim/register-method!
108129
nvim
109130
"eval-code"
@@ -196,8 +217,9 @@
196217
plugin))
197218

198219
(defn new
199-
[nvim repl-log socket-repl]
220+
[nvim nrepl repl-log socket-repl]
200221
{:nvim nvim
222+
:nrepl nrepl
201223
:repl-log repl-log
202224
:socket-repl socket-repl
203225
:code-channel (async/chan 1024)})

src/socket_repl/system.clj

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@
66
[neovim-client.nvim :as nvim]
77
[socket-repl.socket-repl-plugin :as plugin]
88
[socket-repl.repl-log :as repl-log]
9-
[socket-repl.socket-repl :as socket-repl])
9+
[socket-repl.socket-repl :as socket-repl]
10+
[socket-repl.nrepl :as nrepl])
1011
(:gen-class))
1112

1213
(defn new-system*
1314
[nvim]
1415
(let [socket-repl (socket-repl/start (socket-repl/new))
15-
repl-log (repl-log/start (repl-log/new socket-repl))
16-
plugin (plugin/start (plugin/new nvim repl-log socket-repl))]
16+
nrepl (nrepl/start (nrepl/new))
17+
repl-log (repl-log/start (repl-log/new socket-repl nrepl))
18+
plugin (plugin/start (plugin/new nvim nrepl repl-log socket-repl))]
1719
{:nvim nvim
1820
:repl-log repl-log
1921
:socket-repl socket-repl
22+
:nrepl nrepl
2023
:plugin plugin}))
2124

2225
(defn new-system

0 commit comments

Comments
 (0)