feat(lib): add fn!! macro
With implicit positional arguments. Adapted from https://git.sr.ht/~tarsius/llama, minus the font-locking, outer function call, and plus a few minor optimizations. Ref: https://git.sr.ht/~tarsius/llama
This commit is contained in:
parent
5e6689fe5e
commit
17f457edf7
1 changed files with 54 additions and 0 deletions
|
@ -343,6 +343,60 @@ ARGLIST."
|
|||
(allow-other-keys arglist))
|
||||
,@body)))
|
||||
|
||||
(defun doom--fn-crawl (data args)
|
||||
(cond ((symbolp data)
|
||||
(when-let*
|
||||
((lookup '(_ _ %2 %3 %4 %5 %6 %7 %8 %9))
|
||||
(pos (cond ((eq data '%*) 0)
|
||||
((memq data '(% %1)) 1)
|
||||
((cdr (assq data (seq-map-indexed #'cons lookup)))))))
|
||||
(when (and (= pos 1)
|
||||
(aref args 1)
|
||||
(not (eq data (aref args 1))))
|
||||
(error "%% and %%1 are mutually exclusive"))
|
||||
(aset args pos data)))
|
||||
((and (not (eq (car-safe data) '!))
|
||||
(or (listp data)
|
||||
(vectorp data)))
|
||||
(seq-doseq (elt data)
|
||||
(doom--fn-crawl elt args)))))
|
||||
|
||||
(defmacro fn!! (&rest args)
|
||||
"Return an lambda with implicit, positional arguments.
|
||||
|
||||
The function's arguments are determined recursively from ARGS. Each symbol from
|
||||
`%1' through `%9' that appears in ARGS is treated as a positional argument.
|
||||
Missing arguments are named `_%N', which keeps the byte-compiler quiet. `%' is
|
||||
a shorthand for `%1'; only one of these can appear in ARGS. `%*' represents
|
||||
extra `&rest' arguments.
|
||||
|
||||
Instead of:
|
||||
|
||||
(lambda (a _ c &rest d)
|
||||
(if a c (cadr d)))
|
||||
|
||||
you can use this macro and write:
|
||||
|
||||
(fn!! (if %1 %3 (cadr %*)))
|
||||
|
||||
which expands to:
|
||||
|
||||
(lambda (%1 _%2 %3 &rest %*)
|
||||
(if %1 %3 (cadr %*)))
|
||||
|
||||
This macro was adapted from llama.el (see https://git.sr.ht/~tarsius/llama),
|
||||
minus font-locking, the outer function call, and minor optimizations."
|
||||
`(lambda ,(let ((argv (make-vector 10 nil)))
|
||||
(doom--fn-crawl args argv)
|
||||
`(,@(let ((n 0))
|
||||
(mapcar (lambda (sym)
|
||||
(cl-incf n)
|
||||
(or sym (intern (format "_%%%s" n))))
|
||||
(reverse (seq-drop-while
|
||||
#'null (reverse (seq-subseq argv 1))))))
|
||||
,@(and (aref argv 0) '(&rest %*))))
|
||||
,@args))
|
||||
|
||||
(defmacro cmd! (&rest body)
|
||||
"Returns (lambda () (interactive) ,@body)
|
||||
A factory for quickly producing interaction commands, particularly for keybinds
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue