Skip to content

Commit c2b3055

Browse files
committed
Remove global state
1 parent e244ed6 commit c2b3055

File tree

7 files changed

+131
-112
lines changed

7 files changed

+131
-112
lines changed

TODO

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
[_] Replace run-command!, run-command-async! everywhere
2-
[X] samples
3-
[_] socket-repl plugin
4-
[_] Test socket-repl plugin
5-
[_] Squash, merge branch
1+
global-state
2+
[X] finish refactoring nvim, rpc
3+
[X] from debug session, stop, then start (restart) should work
4+
[X] make sure sample plugins still work
5+
[_] clojure socket repl plugin refactor

sample-plugin-simple/src/sample_plugin/core.clj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
(defn -main
66
[& args]
7-
(nvim/connect!)
8-
(nvim/vim-command ":new")
9-
(let [cur-buf (nvim/vim-get-current-buffer)]
10-
(nvim/buffer-set-text! cur-buf "Sample plugin was here!")))
7+
(let [nvim (nvim/new)
8+
cur-buf (nvim/vim-get-current-buffer nvim)]
9+
(nvim/vim-command nvim ":new")
10+
(nvim/buffer-set-text! nvim cur-buf "Sample plugin was here!")))

sample-plugin/src/sample_plugin/core.clj

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,26 @@
44

55
(defn -main
66
[& args]
7-
(nvim/connect!)
8-
9-
(let [x (atom 0)]
7+
(let [nvim (nvim/new)
8+
x (atom 0)]
109
(nvim/register-method!
10+
nvim
1111
"count"
1212
(fn [msg]
1313
;; Plugin can call back to nvim if it wants to, while
1414
;; its doing its own thing.
15-
(nvim/vim-command-async ":echo 'incrementing'"
16-
(fn [_] nil))
15+
(nvim/vim-command-async nvim
16+
":echo 'incrementing'"
17+
(fn [_] nil))
1718
(swap! x inc)
18-
@x)))
19+
@x))
1920

20-
;; Stay alive for a minute!
21-
(dotimes [n 60]
22-
(if (= 0 (mod n 10))
23-
(nvim/vim-command (str ":echo 'plugin alive for " n " seconds.'")))
24-
(Thread/sleep 1000))
21+
;; Stay alive for a minute!
22+
(dotimes [n 60]
23+
(if (= 0 (mod n 10))
24+
(nvim/vim-command nvim (str ":echo 'plugin alive for " n " seconds.'")))
25+
(Thread/sleep 1000))
2526

26-
;; Let nvim know we're shutting down.
27-
(nvim/vim-command ":let g:is_running=0")
28-
(nvim/vim-command ":echo 'plugin stopping.'"))
27+
;; Let nvim know we're shutting down.
28+
(nvim/vim-command nvim ":let g:is_running=0")
29+
(nvim/vim-command nvim ":echo 'plugin stopping.'")))

src/neovim_client/nvim.clj

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@
66

77
;; ***** Public *****
88

9-
(def connect! rpc/connect!)
9+
(def new rpc/new)
1010
(def register-method! rpc/register-method!)
11-
12-
;; TODO - Check for connection, before allowing commands?
11+
(def stop rpc/stop)
1312

1413
(defmacro defvim
1514
[fn-name vim-command & args]
1615
`(do
1716
(defn ~(symbol (str fn-name "-async"))
18-
[~@args f#]
17+
[nvim# ~@args f#]
1918
(rpc/send-message-async!
19+
nvim#
2020
(message/->request-msg ~vim-command [~@args])
2121
f#))
2222
(defn ~fn-name
23-
[~@args]
23+
[nvim# ~@args]
2424
(rpc/send-message!
25+
nvim#
2526
(message/->request-msg ~vim-command [~@args])))))
2627

2728
;; :let g:foo=1
@@ -52,62 +53,66 @@
5253
;; TODO give x, y correct names
5354
(defvim buffer-get-line-slice* "buffer_get_line_slice" buffer start end x y)
5455
(defn buffer-get-line-slice
55-
[buffer start end]
56-
(buffer-get-line-slice* buffer start end true true))
56+
[nvim buffer start end]
57+
(buffer-get-line-slice* nvim buffer start end true true))
5758
(defn buffer-get-line-slice-async
58-
[buffer start end f]
59-
(buffer-get-line-slice*-async buffer start end true true f))
59+
[nvim buffer start end f]
60+
(buffer-get-line-slice*-async nvim buffer start end true true f))
6061

6162
;; ***** Custom *****
6263

6364
;; TODO - fix custom names, move to another ns?
6465

6566
(defn get-cursor-location
6667
"Gets the cursor's current position as a tuple (row, col)."
67-
[]
68-
(window-get-cursor (vim-get-current-window)))
68+
[nvim]
69+
(window-get-cursor nvim (vim-get-current-window nvim)))
6970

7071
(defn get-cursor-location-async
7172
"Gets the cursor's current position as a tuple (row, col) asynchronously."
72-
[f]
73-
(vim-get-current-window-async #(window-get-cursor-async % f)))
73+
[nvim f]
74+
(vim-get-current-window-async nvim #(window-get-cursor-async nvim % f)))
7475

7576
(defn buffer-update-lines!
7677
"Alter each line of the buffer using the function."
77-
[buffer update-fn]
78-
(doseq [n (range (buffer-line-count buffer))]
79-
(buffer-get-line-async buffer n #(buffer-set-line-async buffer n
80-
(update-fn %)
81-
identity))))
78+
[nvim buffer update-fn]
79+
(doseq [n (range (buffer-line-count nvim buffer))]
80+
(buffer-get-line-async nvim buffer n #(buffer-set-line-async nvim
81+
buffer n
82+
(update-fn %)
83+
identity))))
8284
(defn get-current-buffer-text
8385
"Convenience function to get the current buffer's text."
84-
[]
85-
(str/join "\n" (buffer-get-line-slice (vim-get-current-buffer) 0 -1)))
86+
[nvim]
87+
(str/join "\n" (buffer-get-line-slice nvim (vim-get-current-buffer nvim)
88+
0 -1)))
8689

8790
(defn get-current-buffer-text-async
8891
"Convenience function to get the current buffer's text asynchronously."
89-
[f]
92+
[nvim f]
9093
(vim-get-current-buffer-async
94+
nvim
9195
(fn [buffer] (buffer-get-line-slice-async
92-
buffer 0 -1 (fn [lines] (f (str/join "\n" lines)))))))
96+
nvim buffer 0 -1 (fn [lines] (f (str/join "\n" lines)))))))
9397

9498
(defn buffer-set-text!
9599
"Replace the contents of the buffer with `text`."
96-
[buffer text]
100+
[nvim buffer text]
97101
(let [lines (str/split text #"\n")]
98102
(doseq [n (range (count lines))]
99-
(buffer-set-line buffer n (nth lines n)))))
103+
(buffer-set-line nvim buffer n (nth lines n)))))
100104

101105
(defn get-current-word-async
102106
"Get the current word asynchronously."
103-
[f]
104-
(vim-call-function-async "expand" ["<cword>"] f))
107+
[nvim f]
108+
(vim-call-function-async nvim "expand" ["<cword>"] f))
105109

106110
(defn buffer-visible?-async
107111
"Returns a channel which will contain true if the buffer is currently
108112
visible."
109-
[buffer-name]
113+
[nvim buffer-name]
110114
(async/go
111-
(let [visible-buffers (map (comp buffer-get-name window-get-buffer)
112-
(vim-get-windows))]
115+
(let [visible-buffers (map (comp #(buffer-get-name nvim %)
116+
#(window-get-buffer nvim %))
117+
(vim-get-windows nvim))]
113118
((set visible-buffers) buffer-name))))

src/neovim_client/rpc.clj

Lines changed: 69 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,92 +8,105 @@
88
(:import [java.io DataInputStream DataOutputStream]
99
[java.net Socket]))
1010

11-
(def out-chan (atom nil))
12-
(def in-chan (atom nil))
13-
(def msg-table (atom {}))
14-
(def method-table (atom {}))
15-
16-
(defn method-not-found
11+
(defn- method-not-found
1712
[msg]
1813
(log/error "method not found for msg " msg)
1914
(str "method not found - " (method msg)))
2015

21-
(defn create-input-channel
16+
(defn- create-input-channel
2217
"Read messages from the input stream, put them on a channel."
2318
[input-stream]
2419
(let [chan (async/chan 1024)
2520
input-stream (DataInputStream. input-stream)]
26-
(async/go-loop []
27-
(let [msg (msgpack/unpack-stream input-stream)]
21+
(async/go-loop
22+
[]
23+
(when-let [msg (msgpack/unpack-stream input-stream)]
2824
(log/info "stream -> msg -> in chan: " msg)
29-
(async/>! chan msg))
30-
(recur))
31-
chan))
25+
(async/>! chan msg)
26+
(recur)))
27+
[chan input-stream]))
3228

33-
(defn write-msg!
29+
(defn- write-msg!
3430
[packed-msg out-stream]
3531
(doseq [b packed-msg]
3632
(.writeByte out-stream b))
3733
(.flush out-stream))
3834

39-
(defn create-output-channel
35+
(defn- create-output-channel
4036
"Make a channel to read messages from, write to output stream."
4137
[output-stream]
4238
(let [chan (async/chan 1024)
4339
output-stream (DataOutputStream. output-stream)]
44-
(async/go-loop []
45-
(let [msg (async/<! chan)]
40+
(async/go-loop
41+
[]
42+
(when-let [msg (async/<! chan)]
4643
(log/info "stream <- msg <- out chan: " msg)
47-
(write-msg! (msgpack/pack msg) output-stream))
48-
(recur))
44+
(write-msg! (msgpack/pack msg) output-stream)
45+
(recur)))
4946
chan))
5047

51-
(declare send-message-async!)
52-
53-
(defn connect*
54-
[input-stream output-stream]
55-
(reset! in-chan (create-input-channel input-stream))
56-
(reset! out-chan (create-output-channel output-stream))
57-
58-
;; Handle stuff on the input channel -- where should this live?
59-
(async/go-loop []
60-
;; TODO - let the in-chan, if we leave this code here.
61-
(let [msg (async/<! @in-chan)]
62-
(condp = (msg-type msg)
63-
64-
msg/+response+
65-
(let [f (:fn (get @msg-table (id msg)))]
66-
(swap! msg-table dissoc (id msg))
67-
(f (value msg)))
68-
69-
msg/+request+
70-
(let [f (get @method-table (method msg) method-not-found)
71-
result (f msg)]
72-
(send-message-async! (->response-msg (id msg) result) nil))))
73-
(recur)))
74-
7548
;; ***** Public *****
7649

77-
(defn connect!
78-
"Connect to msgpack-rpc channel via standard io or TCP socket."
79-
([] (connect* System/in System/out))
80-
([host port]
81-
(let [socket (java.net.Socket. host port)]
82-
(.setTcpNoDelay socket true)
83-
(connect* (.getInputStream socket) (.getOutputStream socket)))))
84-
8550
(defn send-message-async!
86-
[msg callback-fn]
51+
[{:keys [message-table out-chan]} msg callback-fn]
8752
(if (= msg/+request+ (msg-type msg))
88-
(swap! msg-table assoc (id msg) {:msg msg :fn callback-fn}))
89-
(async/put! @out-chan msg))
53+
(swap! message-table assoc (id msg) {:msg msg :fn callback-fn}))
54+
(async/put! out-chan msg))
9055

9156
(defn send-message!
92-
[msg]
57+
[component msg]
9358
(let [p (promise)]
94-
(send-message-async! msg (partial deliver p))
59+
(send-message-async! component msg (partial deliver p))
9560
@p))
9661

9762
(defn register-method!
98-
[method f]
63+
[{:keys [method-table]} method f]
9964
(swap! method-table assoc method f))
65+
66+
(defn stop
67+
"Stop the connection. Right now, this probably only works for debug, when
68+
connected to socket. Don't think we should be trying to .close STDIO streams."
69+
[{:keys [input-stream output-stream out-chan in-chan data-stream]}]
70+
(async/close! out-chan)
71+
(async/close! in-chan)
72+
(.close data-stream)
73+
(.close input-stream)
74+
(.close output-stream))
75+
76+
(defn new*
77+
[input-stream output-stream]
78+
(let [[in-chan data-stream] (create-input-channel input-stream)
79+
message-table (atom {})
80+
method-table (atom {})
81+
component {:input-stream input-stream
82+
:data-stream data-stream
83+
:output-stream output-stream
84+
:out-chan (create-output-channel output-stream)
85+
:in-chan in-chan
86+
:message-table message-table
87+
:method-table method-table}]
88+
(async/go-loop
89+
[]
90+
(when-let [msg (async/<! in-chan)]
91+
(condp = (msg-type msg)
92+
93+
msg/+response+
94+
(let [f (:fn (get @message-table (id msg)))]
95+
(swap! message-table dissoc (id msg))
96+
(f (value msg)))
97+
98+
msg/+request+
99+
(let [f (get @method-table (method msg) method-not-found)
100+
result (f msg)]
101+
(send-message-async!
102+
component (->response-msg (id msg) result) nil)))
103+
(recur)))
104+
component))
105+
106+
(defn new
107+
"Connect to msgpack-rpc channel via standard io or TCP socket."
108+
([] (new* System/in System/out))
109+
([host port]
110+
(let [socket (java.net.Socket. host port)]
111+
(.setTcpNoDelay socket true)
112+
(new* (.getInputStream socket) (.getOutputStream socket)))))

src/user.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[neovim-client.nvim :as nvim]
44
[clojure.tools.namespace.repl :refer [refresh]]))
55

6-
(defn go
7-
"Start the plugin."
6+
(defn connection
7+
"Get an nvim connection."
88
[]
9-
(nvim/connect! "localhost" 7777))
9+
(nvim/new "localhost" 7777))

tmux-run-dev.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ tmux send-keys "NVIM_LISTEN_ADDRESS=127.0.0.1:7777 nvim" C-m
1010
tmux split
1111
tmux send-keys 'rlwrap java -cp "$(cat .classpath)" clojure.main' C-m
1212
tmux send-keys '(println "Plugin repl connecting to nvim")' C-m
13-
tmux send-keys '(go)' C-m
13+
tmux send-keys '(def c (connection))' C-m

0 commit comments

Comments
 (0)