*** empty log message ***
[bpt/emacs.git] / lisp / custom.el
index 88b03e5..8725e7b 100644 (file)
@@ -5,7 +5,6 @@
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
 ;; Keywords: help, faces
-;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ (probably obsolete)
 
 ;; This file is part of GNU Emacs.
 
@@ -110,7 +109,6 @@ not the default value itself."
   (put symbol 'standard-value (list default))
   ;; Maybe this option was rogue in an earlier version.  It no longer is.
   (when (get symbol 'force-value)
-    ;; It no longer is.
     (put symbol 'force-value nil))
   (when doc
     (put symbol 'variable-documentation doc))
@@ -135,12 +133,12 @@ not the default value itself."
                ((eq keyword :require)
                 (setq requests (cons value requests)))
                ((eq keyword :type)
-                (put symbol 'custom-type value))
+                (put symbol 'custom-type (purecopy value)))
                ((eq keyword :options)
                 (if (get symbol 'custom-options)
                     ;; Slow safe code to avoid duplicates.
-                    (mapcar (lambda (option)
-                              (custom-add-option symbol option))
+                    (mapc (lambda (option)
+                            (custom-add-option symbol option))
                             value)
                   ;; Fast code for the common case.
                   (put symbol 'custom-options (copy-sequence value))))
@@ -187,6 +185,10 @@ The following keywords are meaningful:
        VALUE should be a feature symbol.  If you save a value
        for this option, then when your `.emacs' file loads the value,
        it does (require VALUE) first.
+:version
+        VALUE should be a string specifying that the variable was
+        first introduced, or its default value was changed, in Emacs
+        version VERSION.
 
 Read the section about customization in the Emacs Lisp manual for more
 information."
@@ -300,10 +302,13 @@ The remaining arguments should have the form
 
    [KEYWORD VALUE]...
 
-The following KEYWORD's are defined:
+The following KEYWORDs are defined:
 
-:group  VALUE should be a customization group.
-        Add SYMBOL to that group.
+:group   VALUE should be a customization group.
+         Add SYMBOL to that group.
+
+:version VALUE should be a string specifying that the group was introduced
+         in Emacs version VERSION.
 
 Read the section about customization in the Emacs Lisp manual for more
 information."
@@ -314,12 +319,11 @@ information."
 
 (defun custom-add-to-group (group option widget)
   "To existing GROUP add a new OPTION of type WIDGET.
-If there already is an entry for that option, overwrite it."
-  (let* ((members (get group 'custom-group))
-        (old (assq option members)))
-    (if old
-       (setcar (cdr old) widget)
-      (put group 'custom-group (nconc members (list (list option widget)))))))
+If there already is an entry for OPTION and WIDGET, nothing is done."
+  (let ((members (get group 'custom-group))
+       (entry (list option widget)))
+    (unless (member entry members)
+      (put group 'custom-group (nconc members (list entry))))))
 
 ;;; Properties.
 
@@ -353,9 +357,30 @@ Fourth argument TYPE is the custom option type."
         (custom-add-load symbol value))
        ((eq keyword :tag)
         (put symbol 'custom-tag value))
+       ((eq keyword :set-after)
+        (custom-add-dependencies symbol value))
        (t
         (error "Unknown keyword %s" keyword))))
 
+(defun custom-add-dependencies (symbol value)
+  "To the custom option SYMBOL, add dependencies specified by VALUE.
+VALUE should be a list of symbols.  For each symbol in that list,
+this specifies that SYMBOL should be set after the specified symbol, if
+both appear in constructs like `custom-set-variables'."
+  (unless (listp value)
+    (error "Invalid custom dependency `%s'" value))
+  (let* ((deps (get symbol 'custom-dependencies))
+        (new-deps deps))
+    (while value
+      (let ((dep (car value)))
+       (unless (symbolp dep)
+         (error "Invalid custom dependency `%s'" dep))
+       (unless (memq dep new-deps)
+         (setq new-deps (cons dep new-deps)))
+       (setq value (cdr value))))
+    (unless (eq deps new-deps)
+      (put symbol 'custom-dependencies new-deps))))
+  
 (defun custom-add-option (symbol option)
   "To the variable SYMBOL add OPTION.
 
@@ -404,6 +429,18 @@ If NOW is present and non-nil, VALUE is also evaluated and bound as
 the default value for the SYMBOL.
 REQUEST is a list of features we must require for SYMBOL.
 COMMENT is a comment string about SYMBOL."
+  (setq args
+       (sort args
+             (lambda (a1 a2)
+               (let* ((sym1 (car a1))
+                      (sym2 (car a2))
+                      (1-then-2 (memq sym1 (get sym2 'custom-dependencies)))
+                      (2-then-1 (memq sym2 (get sym1 'custom-dependencies))))
+                 (cond ((and 1-then-2 2-then-1)
+                        (error "Circular custom dependency between `%s' and `%s'"
+                               sym1 sym2))
+                       (2-then-1 nil)
+                       (t t))))))
   (while args
     (let ((entry (car args)))
       (if (listp entry)
@@ -415,13 +452,13 @@ COMMENT is a comment string about SYMBOL."
                 set)
            (when requests
              (put symbol 'custom-requests requests)
-             (mapcar 'require requests))
+             (mapc 'require requests))
            (setq set (or (get symbol 'custom-set) 'custom-set-default))
            (put symbol 'saved-value (list value))
            (put symbol 'saved-variable-comment comment)
            ;; Allow for errors in the case where the setter has
-           ;; changed between versions, say.
-           (condition-case nil
+           ;; changed between versions, say, but let the user know.
+           (condition-case data
                (cond (now
                       ;; Rogue variable, set it now.
                       (put symbol 'force-value t)
@@ -429,7 +466,8 @@ COMMENT is a comment string about SYMBOL."
                      ((default-boundp symbol)
                       ;; Something already set this, overwrite it.
                       (funcall set symbol (eval value))))
-             (error nil))
+             (error 
+              (message "Error setting %s: %s" symbol data)))
            (setq args (cdr args))
            (and (or now (default-boundp symbol))
                 (put symbol 'variable-comment comment)))