diff lisp/specifier.el @ 286:57709be46d1b r21-0b41

Import from CVS: tag r21-0b41
author cvs
date Mon, 13 Aug 2007 10:35:03 +0200
parents 727739f917cb
children e11d67e05968
line wrap: on
line diff
--- a/lisp/specifier.el	Mon Aug 13 10:34:15 2007 +0200
+++ b/lisp/specifier.el	Mon Aug 13 10:35:03 2007 +0200
@@ -403,6 +403,53 @@
 	    how-to-add))))
   value)
 
+;; Note: you cannot replace the following macro with `letf' because
+;; `specifier-instance' does not have a setf method defined.  (I tried
+;; to use `set-specifier' as the setf method for `specifier-instance',
+;; but it doesn't work for `letf' because set-specifier to the old
+;; value cannot be used to "undo" a previous set-specifier, as letf
+;; expects.)
+;;
+;; This macro might perhaps be made simpler, with an addition to
+;; `remove-specifier'.  Example (modulo gensyms for clarity):
+;;
+;; (defmacro with-specifier-instance (specifier value domain &rest body)
+;;   `(unwind-protect
+;;        (progn
+;;	    (add-spec-to-specifier ,specifier ,value ,domain nil 'prepend)
+;;	    ,@body)
+;;      (remove-specifier ,specifier ,domain)))
+;;
+;; So, the idea is to unconditionally prepend a specification for
+;; DOMAIN, and unconditionally remove it.  This does not work because
+;; `remove-specifier' removes *all* the specifications of DOMAIN,
+;; nuking the old ones, in the process.  (for this purpose, it might
+;; make sense for `remove-specifier' to have a HOW-TO-REMOVE
+;; argument.)
+;;
+;; The following version remembers the old speclist and returns it
+;; later.  It's probably less error-prone anyway.
+
+(defmacro with-specifier-instance (specifier value domain &rest body)
+  "Evaluate forms in BODY with SPECIFIER instantiating to VALUE in DOMAIN.
+The value returned is the value of the last form in BODY.
+For meaning of DOMAIN, see `specifier-instance'."
+  (let ((specvar (gensym "wsi-"))
+	(valvar (gensym "wsi-"))
+	(domvar (gensym "wsi-"))
+	(oldvar (gensym "wsi-")))
+    ;; Remember the arguments to prevent multiple evaluation.
+    `(let* ((,specvar ,specifier)
+	    (,valvar ,value)
+	    (,domvar ,domain)
+	    (,oldvar (specifier-spec-list ,specvar ,domvar)))
+       (unwind-protect
+	   (progn
+	     (add-spec-to-specifier ,specvar ,valvar ,domvar nil 'prepend)
+	     ,@body)
+	 (remove-specifier ,specvar ,domvar nil t)
+	 (add-spec-list-to-specifier ,specvar ,oldvar)))))
+
 (define-specifier-tag 'win 'device-on-window-system-p)
 
 ;; Add tags for device types that don't have support compiled