5454
5555(defvar cider-browse-spec-mode-map
5656 (let ((map (make-sparse-keymap )))
57- (set-keymap-parent map cider-popup-buffer-mode-map)
58- (define-key map (kbd " RET" ) #'cider-browse-spec--browse-at-point )
59- (define-key map " n" #'cider-browse-spec--next-spec )
60- (define-key map " p" #'cider-browse-spec--prev-spec )
57+ (set-keymap-parent map (make-composed-keymap button-buffer-map
58+ cider-popup-buffer-mode-map))
59+ (define-key map (kbd " RET" ) #'cider-browse-spec--browse-at )
60+ (define-key map " n" #'forward-button )
61+ (define-key map " p" #'backward-button )
6162 map)
6263 " Keymap for `cider-browse-spec-mode' ." )
6364
64- (defvar cider-browse-spec-mouse-map
65- (let ((map (make-sparse-keymap )))
66- (define-key map [mouse-1] #'cider-browse-spec-handle-mouse )
67- map))
68-
6965(define-derived-mode cider-browse-spec-mode special-mode " Specs"
7066 " Major mode for browsing Clojure specs.
7167
7975(defvar cider-browse-spec-view-mode-map
8076 (let ((map (make-sparse-keymap )))
8177 (set-keymap-parent map help-mode-map)
82- (define-key map (kbd " RET" ) #'cider-browse-spec--browse-at-point )
78+ (define-key map (kbd " RET" ) #'cider-browse-spec--browse-at )
8379 (define-key map " ^" #'cider-browse-spec-all )
8480 (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 )
81+ (define-key map " n" #'forward-button )
82+ (define-key map " p" #'backward-button )
8783 map)
8884 " Keymap for `cider-browse-spec-view-mode' ." )
8985
116112
117113; ; Non interactive functions
118114
119- (defun cider-browse-spec--propertize-keyword (kw )
120- " Add properties to KW text needed by the spec browser."
121- (propertize (cider-font-lock-as-clojure kw)
122- 'spec-name kw
123- 'mouse-face 'highlight
124- 'keymap cider-browse-spec-mouse-map))
125-
126- (defun cider-browse-spec--propertize-fn (fname )
127- " Add properties to FNAME symbol text needed by the spec browser."
128- (propertize fname
129- 'font-lock-face 'font-lock-function-name-face
130- 'spec-name fname
131- 'mouse-face 'highlight
132- 'keymap cider-browse-spec-mouse-map))
115+ (define-button-type 'cider-browse-spec--spec
116+ 'action #'cider-browse-spec--browse-at
117+ 'face nil
118+ 'follow-link t
119+ 'help-echo " View spec" )
133120
134121(defun cider-browse-spec--draw-list-buffer (buffer title specs )
135122 " Reset contents of BUFFER.
@@ -141,12 +128,11 @@ Display TITLE at the top and SPECS are indented underneath."
141128 (goto-char (point-max ))
142129 (insert (cider-propertize title 'emph ) " \n " )
143130 (dolist (spec-name specs)
144- (let ((propertize-fn (if (char-equal (elt spec-name 0 ) ?: )
145- #'cider-browse-spec--propertize-keyword
146- #'cider-browse-spec--propertize-fn )))
147- (thread-first (concat " " (funcall propertize-fn spec-name) " \n " )
148- (propertize 'spec-name spec-name)
149- insert)))
131+ (insert (propertize " " 'spec-name spec-name))
132+ (thread-first (cider-font-lock-as-clojure spec-name)
133+ (insert-text-button 'type 'cider-browse-spec--spec )
134+ (button-put 'spec-name spec-name))
135+ (insert (propertize " \n " 'spec-name spec-name)))
150136 (goto-char (point-min )))))
151137
152138(defun cider--qualified-keyword-p (str )
@@ -161,7 +147,11 @@ Display TITLE at the top and SPECS are indented underneath."
161147 " Given a spec FORM builds a multi line string with a pretty render of that FORM."
162148 (cond ((stringp form)
163149 (if (cider--qualified-keyword-p form)
164- (cider-browse-spec--propertize-keyword form)
150+ (with-temp-buffer
151+ (thread-first form
152+ (insert-text-button 'type 'cider-browse-spec--spec )
153+ (button-put 'spec-name form))
154+ (buffer-string ))
165155 ; ; to make it easier to read replace all clojure.spec ns with s/
166156 ; ; and remove all clojure.core ns
167157 (thread-last form
@@ -284,25 +274,18 @@ a more user friendly representation of SPEC-FORM."
284274 (goto-char (point-min ))
285275 (current-buffer )))
286276
287- ; ; Interactive Functions
277+ (defun cider-browse-spec--browse-at (&optional pos )
278+ " View the definition of a spec.
288279
289- (defun cider-browse-spec--next-spec ()
290- " Move to the next spec in the buffer."
291- (interactive )
292- (when-let ((pos (next-single-property-change (point ) 'spec-name )))
293- (if (get-text-property (point ) 'spec-name )
294- (when-let ((next-pos (next-single-property-change pos 'spec-name )))
295- (goto-char next-pos))
296- (goto-char pos))))
297-
298- (defun cider-browse-spec--prev-spec ()
299- " Move to the previous spec in the buffer."
280+ Optional argument POS is the position of a spec, defaulting to point. POS
281+ may also be a button, so this function can be used a the button's `action'
282+ property."
300283 (interactive )
301- (when- let ((pos (previous-single-property-change (point ) 'spec-name )))
302- (if ( get-text-property ( point ) 'spec-name )
303- ( when-let ((prev-pos ( previous-single-property-change pos ' spec-name )))
304- ( goto-char prev-pos))
305- ( goto-char pos))))
284+ (let ((pos (or pos (point ))))
285+ (when-let ((spec ( button-get pos 'spec-name )) )
286+ (cider-browse-spec--browse spec) )))
287+
288+ ; ; Interactive Functions
306289
307290(defun cider-browse-spec--print-curr-spec-example ()
308291 " Generate and print an example of the current spec."
@@ -355,18 +338,6 @@ No filter applied if the regexp is the empty string."
355338 (format " All specs matching regex `%s' in registry " filter-regex))
356339 specs)))))
357340
358- (defun cider-browse-spec--browse-at-point ()
359- " Go to the definition of the spec at point inside `cider-browse-spec-buffer' ."
360- (interactive )
361- (when-let ((spec (get-text-property (point ) 'spec-name )))
362- (cider-browse-spec--browse spec)))
363-
364- (defun cider-browse-spec-handle-mouse (event )
365- " Handle mouse click EVENT."
366- (interactive " e" )
367- (when (eq 'highlight (get-text-property (point ) 'mouse-face ))
368- (cider-browse-spec--browse-at-point)))
369-
370341(provide 'cider-browse-spec )
371342
372343; ;; cider-browse-spec.el ends here
0 commit comments