+the default value for the SYMBOL.
+REQUEST is a list of features we must 'require for SYMBOL.
+COMMENT is a comment string about SYMBOL."
+ (apply 'custom-theme-set-variables 'user args))
+
+(defun custom-theme-set-variables (theme &rest args)
+ "Initialize variables according to settings specified by args.
+Records the settings as belonging to THEME.
+
+See `custom-set-variables' for a description of the arguments ARGS."
+ (custom-check-theme theme)
+ (let ((immediate (get theme 'theme-immediate)))
+ (while args * etc/custom/example-themes/example-theme.el:
+ (let ((entry (car args)))
+ (if (listp entry)
+ (let* ((symbol (nth 0 entry))
+ (value (nth 1 entry))
+ (now (nth 2 entry))
+ (requests (nth 3 entry))
+ (comment (nth 4 entry))
+ (set (or (get symbol 'custom-set) 'set-default)))
+ (put symbol 'saved-value (list value))
+ (custom-push-theme 'theme-value symbol theme 'set value)
+ (put symbol 'saved-variable-comment comment)
+ (cond ((or now immediate)
+ ;; Rogue variable, set it now.
+ (put symbol 'force-value (if now 'rogue 'immediate))
+ (funcall set symbol (eval value)))
+ ((default-boundp symbol)
+ ;; Something already set this, overwrite it.
+ (funcall set symbol (eval value))))
+ (and (or now (default-boundp symbol))
+ (put symbol 'variable-comment comment))
+ (when requests
+ (put symbol 'custom-requests requests)
+ (mapc 'require requests))
+ (setq args (cdr args)))
+ ;; Old format, a plist of SYMBOL VALUE pairs.
+ (message "Warning: old format `custom-set-variables'")
+ (ding)
+ (sit-for 2)
+ (let ((symbol (nth 0 args))
+ (value (nth 1 args)))
+ (put symbol 'saved-value (list value))
+ (custom-push-theme 'theme-value symbol theme 'set value))
+ (setq args (cdr (cdr args))))))))
+
+(defvar custom-loaded-themes nil
+ "Themes in the order they are loaded.")
+
+(defun custom-theme-loaded-p (theme)
+ "Return non-nil when THEME has been loaded."
+ (memq theme custom-loaded-themes))
+
+(defun provide-theme (theme)
+ "Indicate that this file provides THEME."
+ (custom-check-theme theme)
+ (provide (get theme 'theme-feature))
+ (push theme custom-loaded-themes))
+
+(defun require-theme (theme &optional soft)
+ "Try to load a theme by requiring its feature."
+ ;; Note we do no check for validity of the theme here.
+ ;; This allows to pull in themes by a file-name convention
+ (require (get theme 'theme-feature (custom-make-theme-feature theme))))
+
+(defun custom-do-theme-reset (theme)
+ ; #### untested! slow!
+ (let (spec-list)
+ (mapatoms (lambda (symbol)
+ (setq spec-list (get symbol 'theme-value))
+ (when spec-list
+ (setq spec-list (delete-if (lambda (elt)
+ (eq (car elt) theme))
+ spec-list))
+ (put symbol 'theme-value spec-list)
+ (custom-theme-reset-internal symbol 'user))
+ (setq spec-list (get symbol 'theme-face))
+ (when spec-list
+ (setq spec-list (delete-if (lambda (elt)
+ (eq (car elt) theme))
+ spec-list))
+ (put symbol 'theme-face spec-list)
+ (custom-theme-reset-internal-face symbol 'user))))))
+
+(defun custom-theme-load-themes (by-theme &rest body)
+ "Load the themes specified by BODY and record them as required by
+theme BY-THEME. BODY is a sequence of
+ - a SYMBOL
+ require the theme SYMBOL
+ - a list (reset THEME)
+ Undo all the settings made by THEME.
+ - a list (hidden THEME)
+ require the THEME but hide it from the user."
+ (custom-check-theme by-theme)
+ (dolist (theme body)
+ (cond ((and (consp theme) (eq (car theme) 'reset))
+ (custom-do-theme-reset (cadr theme)))
+ ((and (consp theme) (eq (car theme) 'hidden))
+ (require-theme (cadr theme))
+ (unless (custom-theme-loaded-p (cadr theme))
+ (put (cadr theme) 'theme-hidden t)))
+ (t
+ (require-theme theme)
+ (remprop theme 'theme-hidden)))
+ (push theme (get by-theme 'theme-loads-themes))))
+
+(defun custom-load-themes (&rest body)
+ "Load themes for the USER theme as specified by BODY.
+
+BODY is as with custom-theme-load-themes."
+ (apply #'custom-theme-load-themes 'user body))
+
+
+
+
+(defsubst copy-upto-last (elt list)
+ "Copy all the elements of the list upto the last occurrence of elt."
+ ;; Is it faster to do more work in C than to do less in elisp?
+ (nreverse (cdr (member elt (reverse list)))))
+
+(defun custom-theme-value (theme theme-spec-list)
+ "Determine the value for THEME defined by THEME-SPEC-LIST.
+Returns (list value) if found. Nil otherwise."
+ ;; Note we do _NOT_ signal an error if the theme is unknown
+ ;; it might have gone away without the user knowing.
+ (let ((theme-or-lower (memq theme (cons 'user custom-loaded-themes)))
+ value)
+ (mapc #'(lambda (theme-spec)
+ (when (member (car theme-spec) theme-or-lower)
+ (setq value (cdr theme-spec))
+ ;; We need to continue because if theme =A and we found
+ ;; B then if the load order is B A C B
+ ;; we actually want the value in C.
+ (setq theme-or-lower (copy-upto-last (car theme-spec)
+ theme-or-lower))
+ ;; We could should circuit if this is now nil.
+ ))
+ theme-spec-list)
+ (if value
+ (if (eq (car value) 'set)
+ (list (cadr value))
+ ;; Yet another reset spec. car value = reset
+ (custom-theme-value (cadr value) theme-spec-list)))))
+
+
+(defun custom-theme-variable-value (variable theme)
+ "Return (list value) value of VARIABLE in THEME if the THEME modifies the
+VARIABLE. Nil otherwise."
+ (custom-theme-value theme (get variable 'theme-value)))
+
+(defun custom-theme-reset-internal (symbol to-theme)
+ (let ((value (custom-theme-variable-value symbol to-theme))
+ was-in-theme)
+ (setq was-in-theme value)
+ (setq value (or value (get symbol 'standard-value)))
+ (when value
+ (put symbol 'saved-value was-in-theme)
+ (if (or (get 'force-value symbol) (default-boundp symbol))
+ (funcall (get symbol 'custom-set 'set-default) symbol
+ (eval (car value)))))
+ value))
+
+
+(defun custom-theme-reset-variables (theme &rest args)
+ "Reset the value of the variables to values previously defined.
+Associate this setting with THEME.
+
+ARGS is a list of lists of the form
+
+ (variable to-theme)
+
+This means reset variable to its value in to-theme."
+ (custom-check-theme theme)
+ (mapc #'(lambda (arg)
+ (apply #'custom-theme-reset-internal arg)
+ (custom-push-theme 'theme-value (car arg) theme 'reset (cadr arg)))
+ args))
+
+(defun custom-reset-variables (&rest args)
+ "Reset the value of the variables to values previously defined.
+Associate this setting with the `user' theme.
+
+The ARGS are as in `custom-theme-reset-variables'."
+ (apply #'custom-theme-reset-variables 'user args))
+