|
3 | 3 | Neovim."
|
4 | 4 | (:require
|
5 | 5 | [clojure.core.async :as async]
|
| 6 | + [clojure.edn :as edn] |
6 | 7 | [clojure.java.io :as io]
|
7 | 8 | [clojure.string :as string]
|
8 | 9 | [clojure.tools.namespace.find :as namespace.find]
|
|
28 | 29 | (string/join "\n" (map str (.getStackTrace throwable)))
|
29 | 30 | "\n######################\n")))
|
30 | 31 |
|
31 |
| -(defn run-command |
| 32 | +(defn run-command-async |
32 | 33 | [{:keys [nvim nrepl socket-repl]} f]
|
33 | 34 | (fn [msg]
|
34 | 35 | (if-not (or (socket-repl/connected? socket-repl)
|
|
38 | 39 | nvim ":echo 'Use :Connect host:port to connect to a socket repl'"))
|
39 | 40 | (async/thread (f msg)))
|
40 | 41 | ;; Don't return an async channel, return something msg-pack can serialize.
|
41 |
| - :done)) |
| 42 | + "done")) |
| 43 | + |
| 44 | +(defn run-command |
| 45 | + [{:keys [nvim nrepl socket-repl]} f] |
| 46 | + (fn [msg] |
| 47 | + (if-not (or (socket-repl/connected? socket-repl) |
| 48 | + (nrepl/connected? nrepl)) |
| 49 | + (async/thread |
| 50 | + (api/command |
| 51 | + nvim ":echo 'Use :Connect host:port to connect to a socket repl'")) |
| 52 | + (f msg)))) |
42 | 53 |
|
43 | 54 | (defn get-rlog-buffer
|
44 | 55 | "Returns the buffer w/ b:rlog set, if one exists."
|
|
88 | 99 | (async/>!! (socket-repl/input-channel internal-socket-repl)
|
89 | 100 | '(do
|
90 | 101 | (ns srepl.injection
|
91 |
| - (:refer-clojure :rename {eval core-eval})) |
92 |
| - (defn eval |
93 |
| - ([form] (eval form nil)) |
94 |
| - ([form options] |
95 |
| - (let [result (core-eval form)] |
96 |
| - (merge |
97 |
| - #:socket-repl{:result (pr-str result) |
98 |
| - :form (pr-str form)} |
99 |
| - options)))))) |
| 102 | + (:require |
| 103 | + [clojure.repl :as repl])) |
| 104 | + |
| 105 | + (defonce available-plugins (atom {})) |
| 106 | + |
| 107 | + (try |
| 108 | + (require '[compliment.core :as compliment]) |
| 109 | + (swap! available-plugins assoc :compliment true) |
| 110 | + (catch Exception e |
| 111 | + nil)) |
| 112 | + |
| 113 | + (defn completions |
| 114 | + [prefix options] |
| 115 | + (if |
| 116 | + (:compliment @available-plugins) |
| 117 | + (compliment/completions prefix options) |
| 118 | + (repl/apropos prefix))))) |
100 | 119 | (catch Throwable t
|
101 | 120 | (log/error t "Error connecting to socket repl")
|
102 | 121 | (async/thread (api/command
|
|
125 | 144 | (nvim/register-method!
|
126 | 145 | nvim
|
127 | 146 | "eval"
|
128 |
| - (run-command |
| 147 | + (run-command-async |
129 | 148 | plugin
|
130 | 149 | (fn [msg]
|
131 | 150 | (try
|
|
142 | 161 | (nvim/register-method!
|
143 | 162 | nvim
|
144 | 163 | "eval-form"
|
145 |
| - (run-command |
| 164 | + (run-command-async |
146 | 165 | plugin
|
147 | 166 | (fn [msg]
|
148 | 167 | (let [[row col] (api-ext/get-cursor-location nvim)
|
|
157 | 176 | (nvim/register-method!
|
158 | 177 | nvim
|
159 | 178 | "eval-buffer"
|
160 |
| - (run-command |
| 179 | + (run-command-async |
161 | 180 | plugin
|
162 | 181 | (fn [msg]
|
163 | 182 | (let [buffer (api/get-current-buf nvim)]
|
|
169 | 188 | (nvim/register-method!
|
170 | 189 | nvim
|
171 | 190 | "doc"
|
172 |
| - (run-command |
| 191 | + (run-command-async |
173 | 192 | plugin
|
174 | 193 | (fn [msg]
|
175 | 194 | (let [code (format "(clojure.repl/doc %s)" (-> msg
|
|
180 | 199 | (nvim/register-method!
|
181 | 200 | nvim
|
182 | 201 | "doc-cursor"
|
183 |
| - (run-command |
| 202 | + (run-command-async |
184 | 203 | plugin
|
185 | 204 | (fn [msg]
|
186 | 205 | (api-ext/get-current-word-async
|
|
192 | 211 | (nvim/register-method!
|
193 | 212 | nvim
|
194 | 213 | "source"
|
195 |
| - (run-command |
| 214 | + (run-command-async |
196 | 215 | plugin
|
197 | 216 | (fn [msg]
|
198 | 217 | (let [code (format "(clojure.repl/source %s)" (-> msg
|
|
203 | 222 | (nvim/register-method!
|
204 | 223 | nvim
|
205 | 224 | "source-cursor"
|
206 |
| - (run-command |
| 225 | + (run-command-async |
207 | 226 | plugin
|
208 | 227 | (fn [msg]
|
209 | 228 | (api-ext/get-current-word-async
|
|
214 | 233 |
|
215 | 234 | (nvim/register-method!
|
216 | 235 | nvim
|
217 |
| - "cp" |
| 236 | + "complete-initial" |
218 | 237 | (run-command
|
| 238 | + plugin |
| 239 | + (fn [msg] |
| 240 | + (let [line (api/get-current-line nvim) |
| 241 | + [cursor-row cursor-col] (api-ext/get-cursor-location nvim)] |
| 242 | + (let [start-col (- cursor-col |
| 243 | + (->> line |
| 244 | + (take cursor-col) |
| 245 | + (reverse) |
| 246 | + (take-while #(not (#{\ \(} %))) |
| 247 | + (count)))] |
| 248 | + start-col))))) |
| 249 | + |
| 250 | + (nvim/register-method! |
| 251 | + nvim |
| 252 | + "complete-matches" |
| 253 | + (run-command |
| 254 | + plugin |
| 255 | + (fn [msg] |
| 256 | + (let [word (first (message/params msg)) |
| 257 | + code-form (str "(srepl.injection/completions " |
| 258 | + "\"" word "\" " |
| 259 | + "{:ns *ns*})") |
| 260 | + res-chan (async/chan 1 (filter #(= (:form %) |
| 261 | + code-form)))] |
| 262 | + (try |
| 263 | + (socket-repl/subscribe-output internal-socket-repl res-chan) |
| 264 | + (async/>!! (socket-repl/input-channel internal-socket-repl) code-form) |
| 265 | + (let [matches (async/<!! res-chan) |
| 266 | + r (map (fn [{:keys [candidate type ns] :as match}] |
| 267 | + (log/info (str "Match: " match)) |
| 268 | + {"word" candidate |
| 269 | + "menu" ns |
| 270 | + "kind" (case type |
| 271 | + :function "f" |
| 272 | + :special-form "d" |
| 273 | + :class "t" |
| 274 | + :local "v" |
| 275 | + :keyword "v" |
| 276 | + :resource "t" |
| 277 | + :namespace "t" |
| 278 | + :method "f" |
| 279 | + :static-field "m" |
| 280 | + "")}) |
| 281 | + (edn/read-string (:val matches)))] |
| 282 | + r) |
| 283 | + (finally |
| 284 | + (async/close! res-chan))))))) |
| 285 | + |
| 286 | + (nvim/register-method! |
| 287 | + nvim |
| 288 | + "cp" |
| 289 | + (run-command-async |
219 | 290 | plugin
|
220 | 291 | (fn [msg]
|
221 | 292 | (let [code-form "(map #(.getAbsolutePath %) (clojure.java.classpath/classpath))"]
|
|
230 | 301 | (log/info (:ms res))
|
231 | 302 | (log/info (:val res)))
|
232 | 303 | (finally
|
233 |
| - (.close res-chan))))))))) |
| 304 | + (async/close! res-chan))))))))) |
234 | 305 |
|
235 | 306 | (nvim/register-method!
|
236 | 307 | nvim
|
237 | 308 | "switch-buffer-ns"
|
238 |
| - (run-command |
| 309 | + (run-command-async |
239 | 310 | plugin
|
240 | 311 | (fn [msg]
|
241 | 312 | (let [buffer-name (api/get-current-buf nvim)
|
|
246 | 317 | code-form (if eval-entire-declaration?
|
247 | 318 | namespace-declaration
|
248 | 319 | `(clojure.core/in-ns '~(second namespace-declaration)))]
|
249 |
| - (async/>!! (socket-repl/input-channel socket-repl) code-form))))) |
| 320 | + (async/>!! (socket-repl/input-channel socket-repl) code-form) |
| 321 | + (async/>!! (socket-repl/input-channel internal-socket-repl) code-form))))) |
250 | 322 |
|
251 | 323 | (nvim/register-method!
|
252 | 324 | nvim
|
253 | 325 | "show-log"
|
254 |
| - (run-command |
| 326 | + (run-command-async |
255 | 327 | plugin
|
256 | 328 | (fn [msg]
|
257 | 329 | (let [file (-> repl-log repl-log/file .getAbsolutePath)]
|
|
272 | 344 | (nvim/register-method!
|
273 | 345 | nvim
|
274 | 346 | "dismiss-log"
|
275 |
| - (run-command |
| 347 | + (run-command-async |
276 | 348 | plugin
|
277 | 349 | (fn [msg]
|
278 | 350 | (api/command
|
|
0 commit comments