Skip to content
  • Sponsor clojure-emacs/clojure-mode

  • Notifications You must be signed in to change notification settings
  • Fork 247
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 94ae83f

Browse files
yuhan0yuhan
authored and
yuhan
committedSep 17, 2021
Convert #() fn shorthand
1 parent e1dc7ca commit 94ae83f

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed
 

‎clojure-mode.el

+61
Original file line numberDiff line numberDiff line change
@@ -2767,6 +2767,67 @@ With a numeric prefix argument the let is introduced N lists up."
27672767
(interactive)
27682768
(clojure--move-to-let-internal (read-from-minibuffer "Name of bound symbol: ")))
27692769

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

27712832
;;; Renaming ns aliases
27722833

0 commit comments

Comments
 (0)
Please sign in to comment.