9
9
; ; Artur Malabarba <[email protected] >
10
10
; ; Hugo Duncan <[email protected] >
11
11
; ; Steve Purcell <[email protected] >
12
+ ; ; Arne Brasseur <[email protected] >
12
13
13
14
; ; This program is free software: you can redistribute it and/or modify
14
15
; ; it under the terms of the GNU General Public License as published by
52
53
(require 'cider-client )
53
54
(require 'cider-common )
54
55
(require 'cider-compat )
56
+ (require 'cider-jar )
55
57
(require 'cider-overlays )
56
58
(require 'cider-popup )
57
59
(require 'cider-repl )
@@ -189,29 +191,50 @@ When invoked with a prefix ARG the command doesn't prompt for confirmation."
189
191
190
192
; ;; Sideloader
191
193
192
- (defvar cider-sideloader-dirs
193
- (list (file-name-directory load-file-name))
194
- " Directories where we look for resources requested by the sideloader." )
194
+ (defcustom cider-sideloader-path nil
195
+ " List of directories and jar files to scan for sideloader resources.
196
+ When not set the cider-nrepl jar will be added automatically when upgrading
197
+ an nREPL connection."
198
+ :type 'list
199
+ :group 'cider
200
+ :package-version '(cider . " 0.27.0" ))
201
+
202
+ (defcustom cider-dynload-cider-nrepl-version nil
203
+ " Version of the cider-nrepl jar used for dynamically upgrading a connection.
204
+ Defaults to `cider-required-middleware-version' "
205
+ :type 'string
206
+ :group 'cider
207
+ :package-version '(cider . " 0.27.0" ))
195
208
196
- ; ; based on f-read-bytes
197
209
(defun cider-read-bytes (path )
198
210
" Read binary data from PATH.
199
211
Return the binary data as unibyte string."
212
+ ; ; based on f-read-bytes
200
213
(with-temp-buffer
201
214
(set-buffer-multibyte nil )
202
215
(setq buffer-file-coding-system 'binary )
203
216
(insert-file-contents-literally path nil )
204
217
(buffer-substring-no-properties (point-min ) (point-max ))))
205
218
219
+ (defun cider-retrieve-resource (dirs name )
220
+ " Find a resource NAME in a list DIRS of directories or jar files.
221
+ Similar to a classpath lookup. Returns the file contents as a string."
222
+ (seq-some
223
+ (lambda (path )
224
+ (cond
225
+ ((file-directory-p path)
226
+ (let ((expanded (expand-file-name name path)))
227
+ (when (file-exists-p expanded)
228
+ (cider-read-bytes expanded))))
229
+ ((and (file-exists-p path) (string-suffix-p " .jar" path))
230
+ (cider-jar-retrieve-resource path name))))
231
+ dirs))
232
+
206
233
(defun cider-provide-file (file )
207
234
" Provide FILE in a format suitable for sideloading."
208
- (let ((file (seq-find
209
- #'file-exists-p
210
- (seq-map (lambda (dir )
211
- (expand-file-name file dir))
212
- cider-sideloader-dirs))))
213
- (if file
214
- (base64-encode-string (cider-read-bytes file) 'no-line-breaks )
235
+ (let ((contents (cider-retrieve-resource cider-sideloader-path file)))
236
+ (if contents
237
+ (base64-encode-string contents 'no-line-breaks )
215
238
; ; if we can't find the file we should return an empty string
216
239
(base64-encode-string " " ))))
217
240
@@ -223,6 +246,20 @@ Return the binary data as unibyte string."
223
246
(when (member " sideloader-lookup" status)
224
247
(cider-request:sideloader-provide id type name))))))
225
248
249
+ (defun cider-add-middleware-handler (continue )
250
+ " Make a add-middleware handler.
251
+ CONTINUE is an optional continuation function."
252
+ (lambda (response )
253
+ (nrepl-dbind-response response (status unresolved-middleware) ; ; id middleware
254
+ (when unresolved-middleware
255
+ (seq-do
256
+ (lambda (mw )
257
+ (cider-repl-emit-interactive-stderr
258
+ (concat " WARNING: middleware " mw " was not found or failed to load.\n " )))
259
+ unresolved-middleware))
260
+ (when (and status (member " done" status) continue)
261
+ (funcall continue)))))
262
+
226
263
(defun cider-request:sideloader-start (&optional connection tooling )
227
264
" Perform the nREPL \" sideloader-start\" op.
228
265
If CONNECTION is nil, use `cider-current-repl' .
@@ -253,6 +290,76 @@ If CONNECTION is nil, use `cider-current-repl'."
253
290
(cider-request:sideloader-start connection)
254
291
(cider-request:sideloader-start connection 'tooling ))
255
292
293
+ (defvar cider-nrepl-middlewares
294
+ '(" cider.nrepl/wrap-apropos"
295
+ " cider.nrepl/wrap-classpath"
296
+ " cider.nrepl/wrap-clojuredocs"
297
+ " cider.nrepl/wrap-complete"
298
+ " cider.nrepl/wrap-content-type"
299
+ " cider.nrepl/wrap-debug"
300
+ " cider.nrepl/wrap-enlighten"
301
+ " cider.nrepl/wrap-format"
302
+ " cider.nrepl/wrap-info"
303
+ " cider.nrepl/wrap-inspect"
304
+ " cider.nrepl/wrap-macroexpand"
305
+ " cider.nrepl/wrap-ns"
306
+ " cider.nrepl/wrap-out"
307
+ " cider.nrepl/wrap-slurp"
308
+ " cider.nrepl/wrap-profile"
309
+ " cider.nrepl/wrap-refresh"
310
+ " cider.nrepl/wrap-resource"
311
+ " cider.nrepl/wrap-spec"
312
+ " cider.nrepl/wrap-stacktrace"
313
+ " cider.nrepl/wrap-test"
314
+ " cider.nrepl/wrap-trace"
315
+ " cider.nrepl/wrap-tracker"
316
+ " cider.nrepl/wrap-undef"
317
+ " cider.nrepl/wrap-version"
318
+ " cider.nrepl/wrap-xref" ))
319
+
320
+ (defun cider-request:add-middleware (middlewares
321
+ &optional connection tooling continue )
322
+ " Use the nREPL dynamic loader to add MIDDLEWARES to the nREPL session.
323
+
324
+ - If CONNECTION is nil, use `cider-current-repl' .
325
+ - If TOOLING it truthy, use the tooling session instead of the main session.
326
+ - CONTINUE is an optional continuation function, which will be called when the
327
+ add-middleware op has finished succesfully."
328
+ (cider-nrepl-send-request `(" op" " add-middleware"
329
+ " middleware" , middlewares )
330
+ (cider-add-middleware-handler continue)
331
+ connection
332
+ tooling))
333
+
334
+ (defun cider-add-cider-nrepl-middlewares (&optional connection )
335
+ " Use dynamic loading to add the cider-nrepl middlewares to nREPL.
336
+ If CONNECTION is nil, use `cider-current-repl' ."
337
+ (cider-request:add-middleware
338
+ cider-nrepl-middlewares connection nil
339
+ (lambda ()
340
+ ; ; When the main session is done adding middleware, then do the tooling
341
+ ; ; session. At this point all the namespaces have been sideloaded so this
342
+ ; ; is faster, we don't want these to race to sideload resources.
343
+ (cider-request:add-middleware
344
+ cider-nrepl-middlewares connection 'tooling
345
+ (lambda ()
346
+ ; ; Ask nREPL again what its capabilities are, so we know which new
347
+ ; ; operations are supported.
348
+ (nrepl--init-capabilities (or connection (cider-current-repl))))))))
349
+
350
+ (defvar cider-required-middleware-version )
351
+ (defun cider-upgrade-nrepl-connection (&optional connection )
352
+ " Sideload cider-nrepl middleware.
353
+ If CONNECTION is nil, use `cider-current-repl' ."
354
+ (interactive )
355
+ (when (not cider-sideloader-path)
356
+ (setq cider-sideloader-path (list (cider-jar-find-or-fetch
357
+ " cider" " cider-nrepl"
358
+ (or cider-dynload-cider-nrepl-version
359
+ cider-required-middleware-version)))))
360
+ (cider-sideloader-start connection)
361
+ (cider-add-cider-nrepl-middlewares connection))
362
+
256
363
257
364
; ;; Dealing with compilation (evaluation) errors and warnings
258
365
(defun cider-find-property (property &optional backward )
0 commit comments