emacs/lisp/elephant.el

59 lines
2.0 KiB
EmacsLisp

;;; elephant.el --- Remember variables and modes -*- lexical-binding: t; -*-
;;; Code:
(defmacro elephant-remember (alist)
"Setup a closure remembering symbols to apply with
`remember-reset'. The variables will be renamed using TEMPLATE.
ALIST contains cells of the form (SYMBOL . NEW-VALUE), where
SYMBOL is a variable or mode name, and its value is what to set
after `remember-set'."
(unless lexical-binding
(user-error "`elephant' requires lexical binding."))
(let* ((template (format "elephant--%s-%%s" (gensym)))
(reset-fn (intern (format template "reset"))))
(cl-destructuring-bind (let-list fn-set-list fn-reset-list)
(cl-loop
for (sym . val) in (if (symbolp alist) (symbol-value alist) alist)
as rem = (intern (format template sym))
collect (list rem sym)
into let-list
collect (cond ((eq val 'enable)
`(,sym +1))
((eq val 'disable)
`(,sym -1))
(t `(setq-local ,sym ,val)))
into fn-set-list
collect (cond ((memq val '(enable disable))
`(progn (,sym (if ,rem +1 -1))
(fmakunbound ',rem)))
(t `(progn (setq-local ,sym ,rem)
(makunbound ',rem))))
into fn-reset-list
finally return (list let-list
fn-set-list
fn-reset-list))
`(progn
(defvar-local ,reset-fn nil
"Function to recall values from `elephant-remember'.")
(let ,let-list
(setf (symbol-function ',reset-fn)
(lambda ()
,@fn-reset-list
(redraw-display)
(fmakunbound ',reset-fn))))
,@fn-set-list
',reset-fn))))
(defun elephant-forget ()
"Forget all symbols generated by `elephant-remember'."
)
(provide 'elephant)
;;; elephant.el ends here