diff options
| -rw-r--r-- | NEWS.org | 1 | ||||
| -rw-r--r-- | compat-29.el | 35 | ||||
| -rw-r--r-- | compat-tests.el | 18 | ||||
| -rw-r--r-- | compat.texi | 12 |
4 files changed, 66 insertions, 0 deletions
@@ -13,6 +13,7 @@ - compat-29: Add ~list-of-strings-p~. - compat-29: Add ~delete-line~. - compat-29: Add ~with-narrowing~. +- compat-29: Add ~buffer-local-set-state~ and ~buffer-local-restore-state~. * Release of "Compat" Version 29.1.2.0 diff --git a/compat-29.el b/compat-29.el index 4010a9e..ec5b81e 100644 --- a/compat-29.el +++ b/compat-29.el @@ -171,6 +171,41 @@ This function does not move point. Also see `line-end-position'." ;;;; Defined in subr.el +(compat-defun buffer-local-restore-state (states) + "Restore values of buffer-local variables recorded in STATES. +STATES should be an object returned by `buffer-local-set-state'." + (dolist (state states) + (if (cadr state) + (set (car state) (caddr state)) + (kill-local-variable (car state))))) + +(compat-defun buffer-local-set-state--get (pairs) + "Internal helper function." + (let ((states nil)) + (while pairs + (push (list (car pairs) + (and (boundp (car pairs)) + (local-variable-p (car pairs))) + (and (boundp (car pairs)) + (symbol-value (car pairs)))) + states) + (setq pairs (cddr pairs))) + (nreverse states))) + +(compat-defmacro buffer-local-set-state (&rest pairs) + "Like `setq-local', but allow restoring the previous state of locals later. +This macro returns an object that can be passed to `buffer-local-restore-state' +in order to restore the state of the local variables set via this macro. + +\(fn [VARIABLE VALUE]...)" + (declare (debug setq)) + (unless (zerop (mod (length pairs) 2)) + (error "PAIRS must have an even number of variable/value members")) + `(prog1 + (buffer-local-set-state--get ',pairs) + (,(if (fboundp 'compat--setq-local) 'compat--setq-local 'setq-local) + ,@pairs))) + (compat-defun list-of-strings-p (object) ;; <compat-tests:lists-of-strings-p> "Return t if OBJECT is nil or a list of strings." (declare (pure t) (side-effect-free t)) diff --git a/compat-tests.el b/compat-tests.el index 9b787db..9c8f4dd 100644 --- a/compat-tests.el +++ b/compat-tests.el @@ -908,6 +908,24 @@ (should-equal compat-tests--local-b 2) (should-equal compat-tests--local-c 3)) +(defvar compat-tests--global) +(defvar compat-tests--local) +(defvar compat-tests--unexist) +(ert-deftest buffer-local-set-state () + (setq compat-tests--global 1) + (with-temp-buffer + (setq-local compat-tests--local 2) + (let ((state (buffer-local-set-state compat-tests--global 10 + compat-tests--local 20 + compat-tests--unexist 30))) + (should (= compat-tests--global 10)) + (should (= compat-tests--local 20)) + (should (= compat-tests--unexist 30)) + (buffer-local-restore-state state) + (should (= compat-tests--global 1)) + (should (= compat-tests--local 2)) + (should-not (boundp 'compat-tests--unexist))))) + (ert-deftest gensym () (let ((orig gensym-counter)) (should (integerp gensym-counter)) diff --git a/compat.texi b/compat.texi index 794e724..9295956 100644 --- a/compat.texi +++ b/compat.texi @@ -2012,6 +2012,18 @@ provided by Compat. Note that due to upstream changes, it might happen that there will be the need for changes, so use these functions with care. +@c copied from lispref/modes.texi +@findex buffer-local-restore-state +@defmac buffer-local-set-state variable value... +Minor modes often set buffer-local variables that affect some features +in Emacs. When a minor mode is switched off, the mode is expected to +restore the previous state of these variables. This convenience macro +helps with doing that: It works much like @code{setq-local}, but +returns an object that can be used to restore these values back to +their previous values/states (using the companion function +@code{buffer-local-restore-state}). +@end defmac + @c based on lisp/subr.el @defun delete-line Delete the current line. |
