;;; 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