Skip to content

Commit b3cdb9d

Browse files
committed
Convert #() fn shorthand
1 parent 08986ac commit b3cdb9d

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

clojure-mode.el

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2769,6 +2769,67 @@ With a numeric prefix argument the let is introduced N lists up."
27692769
(interactive)
27702770
(clojure--move-to-let-internal (read-from-minibuffer "Name of bound symbol: ")))
27712771

2772+
;;; Shorthand fn conversion
2773+
(defun clojure--gather-shorthand-args ()
2774+
"Return a cons cell (ARITY . VARARG)
2775+
ARITY is number of arguments in the function,
2776+
VARARG is a boolean of whether it takes a variable argument %&."
2777+
(save-excursion
2778+
(let ((end (save-excursion (clojure-forward-logical-sexp) (point)))
2779+
(rgx (rx symbol-start "%" (group (? (or "&" (+ (in "0-9"))))) symbol-end))
2780+
(arity 0)
2781+
(vararg nil))
2782+
(while (re-search-forward rgx end 'noerror)
2783+
(when (not (or (clojure--in-comment-p) (clojure--in-string-p)))
2784+
(let ((s (match-string 1)))
2785+
(if (string= s "&")
2786+
(setq vararg t)
2787+
(setq arity
2788+
(max arity
2789+
(if (string= s "") 1
2790+
(string-to-number s))))))))
2791+
(cons arity vararg))))
2792+
2793+
(defun clojure--substitute-shorthand-arg (arg sub end)
2794+
"ARG is either a number or the symbol '&.
2795+
SUB is a string to substitute with, and
2796+
END marks the end of the fn expression"
2797+
(save-excursion
2798+
(let ((rgx (format "\\_<%%%s\\_>" (if (eq arg 1) "1?" arg))))
2799+
(while (re-search-forward rgx end 'noerror)
2800+
(when (and (not (clojure--in-comment-p))
2801+
(not (clojure--in-string-p)))
2802+
(replace-match sub))))))
2803+
2804+
(defun clojure-convert-shorthand-fn ()
2805+
"Convert a #(...) function into (fn [...] ...), prompting for the argument names."
2806+
(interactive)
2807+
(when-let (beg (clojure-string-start))
2808+
(goto-char beg))
2809+
(if (or (looking-at-p "#(")
2810+
(forward-char 1)
2811+
(re-search-backward "#(" (save-excursion (beginning-of-defun) (point)) 'noerror))
2812+
(let* ((end (save-excursion (clojure-forward-logical-sexp) (point-marker)))
2813+
(argspec (clojure--gather-shorthand-args))
2814+
(arity (car argspec))
2815+
(vararg (cdr argspec)))
2816+
(delete-char 1)
2817+
(save-excursion (forward-sexp 1) (insert ")"))
2818+
(save-excursion
2819+
(insert "(fn [] ")
2820+
(backward-char 2)
2821+
(mapc (lambda (n)
2822+
(let ((name (read-string (format "Name of argument %d: " n))))
2823+
(when (/= n 1) (insert " "))
2824+
(insert name)
2825+
(clojure--substitute-shorthand-arg n name end)))
2826+
(number-sequence 1 arity))
2827+
(when vararg
2828+
(insert " & ")
2829+
(let ((name (read-string "Name of variadic argument: ")))
2830+
(insert name)
2831+
(clojure--substitute-shorthand-arg '& name end)))))
2832+
(user-error "No #() shorthand at point!")))
27722833

27732834
;;; Renaming ns aliases
27742835

0 commit comments

Comments
 (0)