]> code.delx.au - gnu-emacs/blobdiff - lisp/custom.el
*** empty log message ***
[gnu-emacs] / lisp / custom.el
index 7741ce2e9330f16f664f2b4523ca3b85eb72c0f5..d53951793d24f49c43beca2b45b63c034a574ff5 100644 (file)
@@ -1,7 +1,7 @@
 ;;; custom.el --- tools for declaring and initializing options
 ;;
 ;; Copyright (C) 1996, 1997, 1999, 2001, 2002, 2003, 2004,
-;;   2005 Free Software Foundation, Inc.
+;;   2005, 2006, 2007 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
@@ -203,8 +203,27 @@ The following keywords are meaningful:
 
 :type  VALUE should be a widget type for editing the symbol's value.
 :options VALUE should be a list of valid members of the widget type.
+:initialize
+       VALUE should be a function used to initialize the
+       variable.  It takes two arguments, the symbol and value
+       given in the `defcustom' call.  The default is
+       `custom-initialize-reset'.
+:set   VALUE should be a function to set the value of the symbol.
+       It takes two arguments, the symbol to set and the value to
+       give it.  The default choice of function is `set-default'.
+:get   VALUE should be a function to extract the value of symbol.
+       The function takes one argument, a symbol, and should return
+       the current value for that symbol.  The default choice of function
+       is `default-value'.
+:require
+       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.
+
+The following common keywords are also meaningful.
+
 :group  VALUE should be a customization group.
-        Add SYMBOL to that group.
+        Add SYMBOL (or FACE with `defface') to that group.
 :link LINK-DATA
         Include an external link after the documentation string for this
         item.  This is a sentence containing an active field which
@@ -248,26 +267,19 @@ The following keywords are meaningful:
 
         An item can have more than one external link; however, most items
         have none at all.
-:initialize
-       VALUE should be a function used to initialize the
-       variable.  It takes two arguments, the symbol and value
-       given in the `defcustom' call.  The default is
-       `custom-initialize-reset'.
-:set   VALUE should be a function to set the value of the symbol.
-       It takes two arguments, the symbol to set and the value to
-       give it.  The default choice of function is `custom-set-default'.
-:get   VALUE should be a function to extract the value of symbol.
-       The function takes one argument, a symbol, and should return
-       the current value for that symbol.  The default choice of function
-       is `custom-default-value'.
-:require
-       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.
+:package-version
+        VALUE should be a list with the form (PACKAGE . VERSION)
+        specifying that the variable was first introduced, or its
+        default value was changed, in PACKAGE version VERSION.  This
+        keyword takes priority over :version.  The PACKAGE and VERSION
+        must appear in the alist `customize-package-emacs-version-alist'.
+        Since PACKAGE must be unique and the user might see it in an
+        error message, a good choice is the official name of the
+        package, such as MH-E or Gnus.
 :tag LABEL
         Use LABEL, a string, instead of the item's name, to label the item
         in customization menus and buffers.
@@ -286,8 +298,8 @@ to load a file defining variables with this form, or with
 _outside_ any bindings for these variables.  \(`defvar' and
 `defconst' behave similarly in this respect.)
 
-Read the section about customization in the Emacs Lisp manual for more
-information."
+See Info node `(elisp) Customization' in the Emacs Lisp manual
+for more information."
   (declare (doc-string 3))
   ;; It is better not to use backquote in this file,
   ;; because that makes a bootstrapping problem
@@ -314,10 +326,8 @@ The remaining arguments should have the form
 
    [KEYWORD VALUE]...
 
-The following KEYWORDs are defined:
-
-:group  VALUE should be a customization group.
-        Add FACE to that group.
+For a list of valid keywords, see the common keywords listed in
+`defcustom'.
 
 SPEC should be an alist of the form ((DISPLAY ATTS)...).
 
@@ -368,8 +378,8 @@ corresponding ITEMs.  These are the defined REQ values:
   the function `display-supports-face-attributes-p' for more
   information on exactly how testing is done.
 
-Read the section about customization in the Emacs Lisp manual for more
-information."
+See Info node `(elisp) Customization' in the Emacs Lisp manual
+for more information."
   (declare (doc-string 3))
   ;; It is better not to use backquote in this file,
   ;; because that makes a bootstrapping problem
@@ -426,16 +436,11 @@ The remaining arguments should have the form
 
    [KEYWORD VALUE]...
 
-The following KEYWORDs are defined:
-
-:group   VALUE should be a customization group.
-         Add SYMBOL to that group.
+For a list of valid keywords, see the common keywords listed in
+`defcustom'.
 
-: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."
+See Info node `(elisp) Customization' in the Emacs Lisp manual
+for more information."
   (declare (doc-string 3))
   ;; It is better not to use backquote in this file,
   ;; because that makes a bootstrapping problem
@@ -489,6 +494,8 @@ Fourth argument TYPE is the custom option type."
         (custom-add-to-group value symbol type))
        ((eq keyword :version)
         (custom-add-version symbol value))
+       ((eq keyword :package-version)
+        (custom-add-package-version symbol value))
        ((eq keyword :link)
         (custom-add-link symbol value))
        ((eq keyword :load)
@@ -529,6 +536,7 @@ For other custom types, this has no effect."
   (let ((options (get symbol 'custom-options)))
     (unless (member option options)
       (put symbol 'custom-options (cons option options)))))
+(defalias 'custom-add-frequent-value 'custom-add-option)
 
 (defun custom-add-link (symbol widget)
   "To the custom option SYMBOL add the link WIDGET."
@@ -540,6 +548,10 @@ For other custom types, this has no effect."
   "To the custom option SYMBOL add the version VERSION."
   (put symbol 'custom-version (purecopy version)))
 
+(defun custom-add-package-version (symbol version)
+  "To the custom option SYMBOL add the package version VERSION."
+  (put symbol 'custom-package-version (purecopy version)))
+
 (defun custom-add-load (symbol load)
   "To the custom option SYMBOL add the dependency LOAD.
 LOAD should be either a library file name, or a feature name."
@@ -547,9 +559,10 @@ LOAD should be either a library file name, or a feature name."
     (unless (member load loads)
       (put symbol 'custom-loads (cons (purecopy load) loads)))))
 
-(defun custom-autoload (symbol load)
-  "Mark SYMBOL as autoloaded custom variable and add dependency LOAD."
-  (put symbol 'custom-autoload t)
+(defun custom-autoload (symbol load &optional noset)
+  "Mark SYMBOL as autoloaded custom variable and add dependency LOAD.
+If NOSET is non-nil, don't bother autoloading LOAD when setting the variable."
+  (put symbol 'custom-autoload (if noset 'noset t))
   (custom-add-load symbol load))
 
 ;; This test is also in the C code of `user-variable-p'.
@@ -599,6 +612,116 @@ This recursively follows aliases."
              ((equal load "cus-edit"))
              (t (condition-case nil (load load) (error nil))))))))
 \f
+(defvar custom-local-buffer nil
+  "Non-nil, in a Customization buffer, means customize a specific buffer.
+If this variable is non-nil, it should be a buffer,
+and it means customize the local bindings of that buffer.
+This variable is a permanent local, and it normally has a local binding
+in every Customization buffer.")
+(put 'custom-local-buffer 'permanent-local t)
+
+(defun custom-set-default (variable value)
+  "Default :set function for a customizable variable.
+Normally, this sets the default value of VARIABLE to VALUE,
+but if `custom-local-buffer' is non-nil,
+this sets the local binding in that buffer instead."
+  (if custom-local-buffer
+      (with-current-buffer custom-local-buffer
+       (set variable value))
+    (set-default variable value)))
+
+(defun custom-set-minor-mode (variable value)
+  ":set function for minor mode variables.
+Normally, this sets the default value of VARIABLE to nil if VALUE
+is nil and to t otherwise,
+but if `custom-local-buffer' is non-nil,
+this sets the local binding in that buffer instead."
+  (if custom-local-buffer
+      (with-current-buffer custom-local-buffer
+       (funcall variable (if value 1 0)))
+    (funcall variable (if value 1 0))))
+
+(defun custom-quote (sexp)
+  "Quote SEXP iff it is not self quoting."
+  (if (or (memq sexp '(t nil))
+         (keywordp sexp)
+         (and (listp sexp)
+              (memq (car sexp) '(lambda)))
+         (stringp sexp)
+         (numberp sexp)
+         (vectorp sexp)
+;;;      (and (fboundp 'characterp)
+;;;           (characterp sexp))
+         )
+      sexp
+    (list 'quote sexp)))
+
+(defun customize-mark-to-save (symbol)
+  "Mark SYMBOL for later saving.
+
+If the default value of SYMBOL is different from the standard value,
+set the `saved-value' property to a list whose car evaluates to the
+default value.  Otherwise, set it to nil.
+
+To actually save the value, call `custom-save-all'.
+
+Return non-nil iff the `saved-value' property actually changed."
+  (custom-load-symbol symbol)
+  (let* ((get (or (get symbol 'custom-get) 'default-value))
+        (value (funcall get symbol))
+        (saved (get symbol 'saved-value))
+        (standard (get symbol 'standard-value))
+        (comment (get symbol 'customized-variable-comment)))
+    ;; Save default value iff different from standard value.
+    (if (or (null standard)
+           (not (equal value (condition-case nil
+                                 (eval (car standard))
+                               (error nil)))))
+       (put symbol 'saved-value (list (custom-quote value)))
+      (put symbol 'saved-value nil))
+    ;; Clear customized information (set, but not saved).
+    (put symbol 'customized-value nil)
+    ;; Save any comment that might have been set.
+    (when comment
+      (put symbol 'saved-variable-comment comment))
+    (not (equal saved (get symbol 'saved-value)))))
+
+(defun customize-mark-as-set (symbol)
+  "Mark current value of SYMBOL as being set from customize.
+
+If the default value of SYMBOL is different from the saved value if any,
+or else if it is different from the standard value, set the
+`customized-value' property to a list whose car evaluates to the
+default value.  Otherwise, set it to nil.
+
+Return non-nil iff the `customized-value' property actually changed."
+  (custom-load-symbol symbol)
+  (let* ((get (or (get symbol 'custom-get) 'default-value))
+        (value (funcall get symbol))
+        (customized (get symbol 'customized-value))
+        (old (or (get symbol 'saved-value) (get symbol 'standard-value))))
+    ;; Mark default value as set iff different from old value.
+    (if (not (and old
+                  (equal value (condition-case nil
+                                   (eval (car old))
+                                 (error nil)))))
+       (progn (put symbol 'customized-value (list (custom-quote value)))
+              (custom-push-theme 'theme-value symbol 'user 'set
+                                 (custom-quote value)))
+      (put symbol 'customized-value nil))
+    ;; Changed?
+    (not (equal customized (get symbol 'customized-value)))))
+
+(defun custom-reevaluate-setting (symbol)
+  "Reset the value of SYMBOL by re-evaluating its saved or standard value.
+Use the :set function to do so.  This is useful for customizable options
+that are defined before their standard value can really be computed.
+E.g. dumped variables whose default depends on run-time information."
+  (funcall (or (get symbol 'custom-set) 'set-default)
+          symbol
+          (eval (car (or (get symbol 'saved-value) (get symbol 'standard-value))))))
+
+\f
 ;;; Custom Themes
 
 ;; Custom themes are collections of settings that can be enabled or
@@ -644,8 +767,6 @@ This recursively follows aliases."
 ;; `theme-face' properties, but the theme's own `theme-settings'
 ;; property remains unchanged.
 
-;;; Defining themes
-
 (defvar custom-known-themes '(user changed)
    "Themes that have been defined with `deftheme'.
 The default value is the list (user changed).  The theme `changed'
@@ -706,27 +827,21 @@ See `custom-known-themes' for a list of known themes."
        ;; theme is later disabled.
        (if (null old)
            (if (and (eq prop 'theme-value)
-                    (boundp symbol)
-                    (or (null (get symbol 'standard-value))
-                        (not (equal (eval (car (get symbol 'standard-value)))
-                                    (symbol-value symbol)))))
-               (setq old (list (list 'changed (symbol-value symbol))))
-             (if (facep symbol)
+                    (boundp symbol))
+               (let ((sv (get symbol 'standard-value)))
+                 (unless (and sv
+                               (equal (eval (car sv)) (symbol-value symbol)))
+                    (setq old (list (list 'changed (symbol-value symbol))))))
+             (if (and (facep symbol)
+                      (not (face-spec-match-p symbol (get symbol 'face-defface-spec))))
                  (setq old (list (list 'changed (list
                    (append '(t) (custom-face-attributes-get symbol nil)))))))))
        (put symbol prop (cons (list theme value) old))
        (put theme 'theme-settings
             (cons (list prop symbol theme value)
                   theme-settings))))))
-\f
-(defvar custom-local-buffer nil
-  "Non-nil, in a Customization buffer, means customize a specific buffer.
-If this variable is non-nil, it should be a buffer,
-and it means customize the local bindings of that buffer.
-This variable is a permanent local, and it normally has a local binding
-in every Customization buffer.")
-(put 'custom-local-buffer 'permanent-local t)
 
+\f
 (defun custom-set-variables (&rest args)
   "Install user customizations of variable values specified in ARGS.
 These settings are registered as theme `user'.
@@ -743,15 +858,6 @@ handle SYMBOL properly.
 COMMENT is a comment string about SYMBOL."
   (apply 'custom-theme-set-variables 'user args))
 
-(defun custom-reevaluate-setting (symbol)
-  "Reset the value of SYMBOL by re-evaluating its saved or standard value.
-Use the :set function to do so.  This is useful for customizable options
-that are defined before their standard value can really be computed.
-E.g. dumped variables whose default depends on run-time information."
-  (funcall (or (get symbol 'custom-set) 'set-default)
-          symbol
-          (eval (car (or (get symbol 'saved-value) (get symbol 'standard-value))))))
-
 (defun custom-theme-set-variables (theme &rest args)
   "Initialize variables for theme THEME according to settings in ARGS.
 Each of the arguments in ARGS should be a list of this form:
@@ -766,19 +872,21 @@ REQUEST is a list of features we must require in order to
 handle SYMBOL properly.
 COMMENT is a comment string about SYMBOL.
 
-Several properties of THEME and SYMBOL are used in the process:
-
-If THEME's property `theme-immediate' is non-nil, this is equivalent of
-providing the NOW argument to all symbols in the argument list:
-evaluate each EXP and set the corresponding SYMBOL.  However,
-there's a difference in the handling of SYMBOL's property
-`force-value': if NOW is non-nil, SYMBOL's property `force-value' is set to
-the symbol `rogue', else if THEME's property `theme-immediate' is non-nil,
-SYMBOL's property `force-value' is set to the symbol `immediate'.
-
 EXP itself is saved unevaluated as SYMBOL property `saved-value' and
 in SYMBOL's list property `theme-value' \(using `custom-push-theme')."
   (custom-check-theme theme)
+  ;; Process all the needed autoloads before anything else, so that the
+  ;; subsequent code has all the info it needs (e.g. which var corresponds
+  ;; to a minor mode), regardless of the ordering of the variables.
+  (dolist (entry args)
+    (let* ((symbol (indirect-variable (nth 0 entry))))
+      (unless (or (get symbol 'standard-value)
+                  (memq (get symbol 'custom-autoload) '(nil noset)))
+        ;; This symbol needs to be autoloaded, even just for a `set'.
+        (custom-load-symbol symbol))))
+  ;; Move minor modes and variables with explicit requires to the end.
   (setq args
        (sort args
              (lambda (a1 a2)
@@ -828,6 +936,8 @@ in SYMBOL's list property `theme-value' \(using `custom-push-theme')."
            (setq args (cdr args))
            (and (or now (default-boundp symbol))
                 (put symbol 'variable-comment comment)))
+        ;; I believe this is dead-code, because the `sort' code above would
+        ;; have burped before we could get here.  --Stef
        ;; Old format, a plist of SYMBOL VALUE pairs.
        (message "Warning: old format `custom-set-variables'")
        (ding)
@@ -838,93 +948,6 @@ in SYMBOL's list property `theme-value' \(using `custom-push-theme')."
          (custom-push-theme 'theme-value symbol theme 'set value))
        (setq args (cdr (cdr args)))))))
 
-(defun custom-set-default (variable value)
-  "Default :set function for a customizable variable.
-Normally, this sets the default value of VARIABLE to VALUE,
-but if `custom-local-buffer' is non-nil,
-this sets the local binding in that buffer instead."
-  (if custom-local-buffer
-      (with-current-buffer custom-local-buffer
-       (set variable value))
-    (set-default variable value)))
-
-(defun custom-set-minor-mode (variable value)
-  ":set function for minor mode variables.
-Normally, this sets the default value of VARIABLE to nil if VALUE
-is nil and to t otherwise,
-but if `custom-local-buffer' is non-nil,
-this sets the local binding in that buffer instead."
-  (if custom-local-buffer
-      (with-current-buffer custom-local-buffer
-       (funcall variable (if value 1 0)))
-    (funcall variable (if value 1 0))))
-
-(defun custom-quote (sexp)
-  "Quote SEXP iff it is not self quoting."
-  (if (or (memq sexp '(t nil))
-         (keywordp sexp)
-         (and (listp sexp)
-              (memq (car sexp) '(lambda)))
-         (stringp sexp)
-         (numberp sexp)
-         (vectorp sexp)
-;;;      (and (fboundp 'characterp)
-;;;           (characterp sexp))
-         )
-      sexp
-    (list 'quote sexp)))
-
-(defun customize-mark-to-save (symbol)
-  "Mark SYMBOL for later saving.
-
-If the default value of SYMBOL is different from the standard value,
-set the `saved-value' property to a list whose car evaluates to the
-default value.  Otherwise, set it to nil.
-
-To actually save the value, call `custom-save-all'.
-
-Return non-nil iff the `saved-value' property actually changed."
-  (let* ((get (or (get symbol 'custom-get) 'default-value))
-        (value (funcall get symbol))
-        (saved (get symbol 'saved-value))
-        (standard (get symbol 'standard-value))
-        (comment (get symbol 'customized-variable-comment)))
-    ;; Save default value iff different from standard value.
-    (if (or (null standard)
-           (not (equal value (condition-case nil
-                                 (eval (car standard))
-                               (error nil)))))
-       (put symbol 'saved-value (list (custom-quote value)))
-      (put symbol 'saved-value nil))
-    ;; Clear customized information (set, but not saved).
-    (put symbol 'customized-value nil)
-    ;; Save any comment that might have been set.
-    (when comment
-      (put symbol 'saved-variable-comment comment))
-    (not (equal saved (get symbol 'saved-value)))))
-
-(defun customize-mark-as-set (symbol)
-  "Mark current value of SYMBOL as being set from customize.
-
-If the default value of SYMBOL is different from the saved value if any,
-or else if it is different from the standard value, set the
-`customized-value' property to a list whose car evaluates to the
-default value.  Otherwise, set it to nil.
-
-Return non-nil iff the `customized-value' property actually changed."
-  (let* ((get (or (get symbol 'custom-get) 'default-value))
-        (value (funcall get symbol))
-        (customized (get symbol 'customized-value))
-        (old (or (get symbol 'saved-value) (get symbol 'standard-value))))
-    ;; Mark default value as set iff different from old value.
-    (if (or (null old)
-           (not (equal value (condition-case nil
-                                 (eval (car old))
-                               (error nil)))))
-       (put symbol 'customized-value (list (custom-quote value)))
-      (put symbol 'customized-value nil))
-    ;; Changed?
-    (not (equal customized (get symbol 'customized-value)))))
 \f
 ;;; Defining themes.
 
@@ -1016,11 +1039,17 @@ property `theme-feature' (which is usually a symbol created by
     (enable-theme 'user)))
 
 (defun load-theme (theme)
-  "Try to load a theme's settings from its file.
+  "Load a theme's settings from its file.
 This also enables the theme; use `disable-theme' to disable it."
   ;; Note we do no check for validity of the theme here.
   ;; This allows to pull in themes by a file-name convention
   (interactive "SCustom theme name: ")
+  ;; If reloading, clear out the old theme settings.
+  (when (custom-theme-p theme)
+    (disable-theme theme)
+    (put theme 'theme-settings nil)
+    (put theme 'theme-feature nil)
+    (put theme 'theme-documentation nil))
   (let ((load-path (if (file-directory-p custom-theme-directory)
                       (cons custom-theme-directory load-path)
                     load-path)))
@@ -1151,7 +1180,7 @@ Each of the arguments ARGS has this form:
 
     (VARIABLE IGNORED)
 
-This means reset VARIABLE.  (The argument IGNORED is ignored."
+This means reset VARIABLE.  (The argument IGNORED is ignored)."
   (custom-check-theme theme)
   (dolist (arg args)
     (custom-push-theme 'theme-value (car arg) theme 'reset)))
@@ -1164,7 +1193,7 @@ Each of the arguments ARGS has this form:
 
     (VARIABLE IGNORED)
 
-This means reset VARIABLE.  (The argument IGNORED is ignored."
+This means reset VARIABLE.  (The argument IGNORED is ignored)."
     (apply 'custom-theme-reset-variables 'user args))
 
 ;;; The End.