;;; 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
: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
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.
_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
[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)...).
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
[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
(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)
(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."
"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."
(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'.
((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
;; `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'
;; 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'.
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:
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)
(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)
(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.
(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)))
(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)))
(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.