25
25
; ;
26
26
; ; Display a spec description you can browse.
27
27
; ; Pressing <enter> over a sub spec will take you to the description of that sub spec.
28
- ; ; Pressing ^ will take you up in the navigation stack .
28
+ ; ; Pressing ^ takes you to the list of all specs .
29
29
30
30
; ; M-x cider-browse-spec-all
31
31
; ;
47
47
(defconst cider-browse-spec-buffer " *cider-spec-browser*" )
48
48
(add-to-list 'cider-ancillary-buffers cider-browse-spec-buffer)
49
49
50
- (defvar cider-browse-spec-navigation '()
51
- " Keeps the cider spec browser navigation stack.
52
- A list of strings which are specs or specs searches.
53
- First of the list is the top of the stack.
54
- Specs searches are encoded as (search \" regex\" )
55
- For example: (\" :ring.request/header-name\" \" :ring.request/headers\" \" :ring/request\" (search \" ring.+\" ))" )
56
50
(defconst cider-browse-spec-example-buffer " *cider-spec-example*" )
57
51
(add-to-list 'cider-ancillary-buffers cider-browse-spec-example-buffer)
58
52
@@ -62,11 +56,10 @@ For example: (\":ring.request/header-name\" \":ring.request/headers\" \":ring/re
62
56
(let ((map (make-sparse-keymap )))
63
57
(set-keymap-parent map cider-popup-buffer-mode-map)
64
58
(define-key map (kbd " RET" ) #'cider-browse-spec--browse-at-point )
65
- (define-key map " ^" #'cider-browse-spec--navigate-back )
66
59
(define-key map " n" #'cider-browse-spec--next-spec )
67
60
(define-key map " p" #'cider-browse-spec--prev-spec )
68
- ( define-key map " e " # 'cider-browse-spec--print-curr-spec-example )
69
- map) )
61
+ map)
62
+ " Keymap for `cider-browse-spec-mode' . " )
70
63
71
64
(defvar cider-browse-spec-mouse-map
72
65
(let ((map (make-sparse-keymap )))
@@ -81,11 +74,47 @@ For example: (\":ring.request/header-name\" \":ring.request/headers\" \":ring/re
81
74
(when cider-special-mode-truncate-lines
82
75
(setq-local truncate-lines t )))
83
76
84
- ; ; Non interactive functions
77
+ (defvar cider-browse-spec--current-spec nil )
78
+
79
+ (defvar cider-browse-spec-view-mode-map
80
+ (let ((map (make-sparse-keymap )))
81
+ (set-keymap-parent map help-mode-map)
82
+ (define-key map (kbd " RET" ) #'cider-browse-spec--browse-at-point )
83
+ (define-key map " ^" #'cider-browse-spec-all )
84
+ (define-key map " e" #'cider-browse-spec--print-curr-spec-example )
85
+ (define-key map " n" #'cider-browse-spec--next-spec )
86
+ (define-key map " p" #'cider-browse-spec--prev-spec )
87
+ map)
88
+ " Keymap for `cider-browse-spec-view-mode' ." )
85
89
86
- (defun cider-browse-spec--clear-nav-history ()
87
- " Clears `cider-browse-spec-navigation' ."
88
- (setq cider-browse-spec-navigation '()))
90
+ (define-derived-mode cider-browse-spec-view-mode help-mode " Spec view"
91
+ " Major mode for displaying CIDER spec.
92
+
93
+ \\ {cider-browse-spec-view-mode-map}"
94
+ (setq-local cider-browse-spec--current-spec nil )
95
+ (setq-local electric-indent-chars nil )
96
+ (when cider-special-mode-truncate-lines
97
+ (setq-local truncate-lines t )))
98
+
99
+ (defvar cider-browse-spec-example-mode-map
100
+ (let ((map (make-sparse-keymap )))
101
+ (set-keymap-parent map cider-popup-buffer-mode-map)
102
+ (define-key map " ^" #'cider-browse-spec-all )
103
+ (define-key map " e" #'cider-browse-spec--print-curr-spec-example )
104
+ (define-key map " g" #'revert-buffer )
105
+ map)
106
+ " Keymap for `cider-browse-spec-example-mode' ." )
107
+
108
+ (define-derived-mode cider-browse-spec-example-mode special-mode " Example"
109
+ " Major mode for Clojure spec examples.
110
+
111
+ \\ {cider-browse-spec-example-mode-map}"
112
+ (setq-local electric-indent-chars nil )
113
+ (setq-local revert-buffer-function #'cider-browse-spec--example-revert-buffer-function )
114
+ (when cider-special-mode-truncate-lines
115
+ (setq-local truncate-lines t )))
116
+
117
+ ; ; Non interactive functions
89
118
90
119
(defun cider-browse-spec--propertize-keyword (kw )
91
120
" Add properties to KW text needed by the spec browser."
@@ -220,8 +249,8 @@ Display TITLE at the top and SPECS are indented underneath."
220
249
(format " (s/fspec \n %s ) " )))
221
250
; ; every other with no special management
222
251
(t (format " (%s %s ) "
223
- (cider-browse-spec--pprint form-tag)
224
- (string-join (mapcar #'cider-browse-spec--pprint (cl-rest form)) " " ))))))
252
+ (cider-browse-spec--pprint form-tag)
253
+ (string-join (mapcar #'cider-browse-spec--pprint (cl-rest form)) " " ))))))
225
254
(t (format " %s " form))))
226
255
227
256
(defun cider-browse-spec--draw-spec-buffer (buffer spec spec-form )
@@ -230,8 +259,7 @@ Display SPEC as a title and uses `cider-browse-spec--pprint' to display
230
259
a more user friendly representation of SPEC-FORM."
231
260
(with-current-buffer buffer
232
261
(let ((inhibit-read-only t ))
233
- (cider-browse-spec-mode)
234
- (erase-buffer )
262
+ (cider--help-setup-xref (list #'cider-browse-spec spec) nil buffer)
235
263
(goto-char (point-max ))
236
264
(insert (cider-font-lock-as-clojure spec) " \n\n " )
237
265
(insert (with-temp-buffer
@@ -240,25 +268,21 @@ a more user friendly representation of SPEC-FORM."
240
268
(indent-region (point-min ) (point-max ))
241
269
(font-lock-ensure )
242
270
(buffer-string )))
243
- (insert " \n\n " )
244
- (insert-text-button " [Back]"
245
- 'action (lambda (b ) (call-interactively 'cider-browse-spec--navigate-back ))
246
- 'follow-link t )
247
- (goto-char (point-min )))))
271
+ (cider--make-back-forward-xrefs)
272
+ (current-buffer ))))
248
273
249
274
(defun cider-browse-spec--browse (spec )
250
- " Browse SPEC pushing it into `cider-browse-spec-navigation' ."
275
+ " Browse SPEC."
276
+ (cider-ensure-connected)
277
+ (cider-ensure-op-supported " spec-form" )
251
278
(with-current-buffer (cider-popup-buffer cider-browse-spec-buffer t )
252
- (push spec cider-browse-spec-navigation)
279
+ (cider-browse-spec-view-mode)
280
+ (setq-local cider-browse-spec--current-spec spec)
253
281
(cider-browse-spec--draw-spec-buffer (current-buffer )
254
- spec
255
- (cider-sync-request:spec-form spec))))
256
-
257
- (defun cider-browse-spec--is-nav-searchp (str-filter )
258
- " Return non nil if STR-FILTER is a filter term."
259
- (and (listp str-filter)
260
- (eq (car str-filter) 'search )))
261
-
282
+ spec
283
+ (cider-sync-request:spec-form spec))
284
+ (goto-char (point-min ))
285
+ (current-buffer )))
262
286
263
287
; ; Interactive Functions
264
288
@@ -267,7 +291,7 @@ a more user friendly representation of SPEC-FORM."
267
291
(interactive )
268
292
(goto-char (next-single-property-change (point ) 'spec-name ))
269
293
(unless (get-text-property (point ) 'spec-name )
270
- (goto-char (next-single-property-change (point ) 'spec-name ))))
294
+ (goto-char (next-single-property-change (point ) 'spec-name ))))
271
295
272
296
(defun cider-browse-spec--prev-spec ()
273
297
" Move to the previous spec in the buffer."
@@ -277,66 +301,62 @@ a more user friendly representation of SPEC-FORM."
277
301
(goto-char (previous-single-property-change (point ) 'spec-name ))))
278
302
279
303
(defun cider-browse-spec--print-curr-spec-example ()
280
- " Generate and print a spec example of the current spec in `cider-browse-spec-navigation' ."
304
+ " Generate and print an example of the current spec."
281
305
(interactive )
282
- (when cider-browse-spec-navigation
283
- (let* ((spec (cl-first cider-browse-spec-navigation))
284
- (example (cider-sync-request:spec-example spec)))
285
- (with-current-buffer (cider-popup-buffer cider-browse-spec-example-buffer t )
286
- (cider-browse-spec-mode)
287
- (let ((inhibit-read-only t ))
288
- (erase-buffer )
289
- (goto-char (point-max ))
290
- (insert (cider-propertize (concat " Example of: " spec) 'emph ) " \n\n " )
291
- (insert example)
292
- (goto-char (point-min )))))))
306
+ (cider-ensure-connected)
307
+ (cider-ensure-op-supported " spec-example" )
308
+ (if-let ((spec cider-browse-spec--current-spec))
309
+ (if-let ((example (cider-sync-request:spec-example spec)))
310
+ (with-current-buffer (cider-popup-buffer cider-browse-spec-example-buffer t )
311
+ (cider-browse-spec-example-mode)
312
+ (setq-local cider-browse-spec--current-spec spec)
313
+ (let ((inhibit-read-only t ))
314
+ (insert " Example of " (cider-font-lock-as-clojure spec))
315
+ (insert " \n\n " )
316
+ (insert (cider-font-lock-as-clojure example))
317
+ (goto-char (point-min ))))
318
+ (error (format " No example for spec %s " spec)))
319
+ (error " No current spec " )))
320
+
321
+ (defun cider-browse-spec--example-revert-buffer-function (&rest _ )
322
+ " `revert-buffer' function for `cider-browse-spec-example-mode' .
323
+
324
+ Generates a new example for the current spec."
325
+ (cider-browse-spec--print-curr-spec-example))
293
326
294
327
;;;### autoload
295
328
(defun cider-browse-spec (spec )
296
- " Start a new navigation and browse to SPEC definition."
329
+ " Browse SPEC definition."
297
330
(interactive (list (completing-read " Browse spec: "
298
331
(cider-sync-request:spec-list)
299
332
nil nil
300
333
(cider-symbol-at-point))))
301
- (cider-browse-spec--clear-nav-history)
302
334
(cider-browse-spec--browse spec))
303
335
304
-
305
336
;;;### autoload
306
- (defun cider-browse-spec-all (&optional filter-regex )
307
- " List all loaded specs in BUFFER filtered by FILTER-REGEX.
308
-
309
- Optional argument FILTER-REGEX is a regexp string matching spec names. The
310
- default value, \"\" , matches all specs in the registry."
311
- (interactive (list (read-string " Filter regex: " )))
312
- (with-current-buffer (cider-popup-buffer cider-browse-spec-buffer t )
313
- (let ((specs (cider-sync-request:spec-list filter-regex)))
314
- (cider-browse-spec--clear-nav-history)
315
- (push `(search , filter-regex ) cider-browse-spec-navigation)
316
- (cider-browse-spec--draw-list-buffer (current-buffer )
317
- (if (string-empty-p filter-regex)
318
- " All specs in registry"
319
- (format " All specs matching regex `%s' in registry " filter-regex))
320
- specs))))
337
+ (defun cider-browse-spec-all (&optional arg )
338
+ " Open list of specs in a popup buffer.
339
+
340
+ With a prefix argument ARG, prompts for a regexp to filter specs.
341
+ No filter applied if the regexp is the empty string."
342
+ (interactive " P" )
343
+ (cider-ensure-connected)
344
+ (cider-ensure-op-supported " spec-list" )
345
+ (let ((filter-regex (if arg (read-string " Filter regex: " ) " " )))
346
+ (with-current-buffer (cider-popup-buffer cider-browse-spec-buffer t )
347
+ (let ((specs (cider-sync-request:spec-list filter-regex)))
348
+ (cider-browse-spec--draw-list-buffer (current-buffer )
349
+ (if (string-empty-p filter-regex)
350
+ " All specs in registry"
351
+ (format " All specs matching regex `%s' in registry " filter-regex))
352
+ specs)))))
321
353
322
354
(defun cider-browse-spec--browse-at-point ()
323
355
" Go to the definition of the spec at point inside `cider-browse-spec-buffer' ."
324
356
(interactive )
325
357
(when-let ((spec (get-text-property (point ) 'spec-name )))
326
358
(cider-browse-spec--browse spec)))
327
359
328
- (defun cider-browse-spec--navigate-back ()
329
- " Move the browser back in `cider-browse-spec-navigation' ."
330
- (interactive )
331
- (if (> (length cider-browse-spec-navigation) 1 )
332
- (progn
333
- (pop cider-browse-spec-navigation) ; ; discard current
334
- (if (cider-browse-spec--is-nav-searchp (cl-first cider-browse-spec-navigation))
335
- (cider-browse-spec-all (cl-second (pop cider-browse-spec-navigation)))
336
- (cider-browse-spec--browse (pop cider-browse-spec-navigation))))
337
- (unless (cider-browse-spec--is-nav-searchp (cl-first cider-browse-spec-navigation))
338
- (cider-browse-spec-all))))
339
-
340
360
(defun cider-browse-spec-handle-mouse (event )
341
361
" Handle mouse click EVENT."
342
362
(interactive " e" )
0 commit comments