;;; custom.el -- Tools for declaring and initializing options.
;;
-;; Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc.
;;
;; 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.
(defun custom-initialize-changed (symbol value)
"Initialize SYMBOL with VALUE.
-Like `custom-initialize-reset', but only use the `:set' function if the
+Like `custom-initialize-reset', but only use the `:set' function if
not using the standard setting.
-For the standard setting, use the `set-default'."
+For the standard setting, use `set-default'."
(cond ((default-boundp symbol)
(funcall (or (get symbol 'custom-set) 'set-default)
symbol
(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))
((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))))
The following keywords are meaningful:
:type VALUE should be a widget type for editing the symbols value.
- The default is `sexp'.
:options VALUE should be a list of valid members of the widget type.
:group VALUE should be a customization group.
Add SYMBOL to that group.
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."
(setq members (cdr members)))
(put symbol 'custom-group (nconc members (get symbol 'custom-group)))
(when doc
- (put symbol 'group-documentation doc))
+ ;; This text doesn't get into DOC.
+ (put symbol 'group-documentation (purecopy doc)))
(while args
(let ((arg (car args)))
(setq args (cdr args))
[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."
(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.
(defun custom-handle-keyword (symbol keyword value type)
"For customization option SYMBOL, handle KEYWORD with VALUE.
Fourth argument TYPE is the custom option type."
+ (if purify-flag
+ (setq value (purecopy value)))
(cond ((eq keyword :group)
(custom-add-to-group value symbol type))
((eq keyword :version)
(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.
"To the custom option SYMBOL add the link WIDGET."
(let ((links (get symbol 'custom-links)))
(unless (member widget links)
- (put symbol 'custom-links (cons widget links)))))
+ (put symbol 'custom-links (cons (purecopy widget) links)))))
(defun custom-add-version (symbol version)
"To the custom option SYMBOL add the version VERSION."
- (put symbol 'custom-version version))
+ (put symbol 'custom-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."
(let ((loads (get symbol 'custom-loads)))
(unless (member load loads)
- (put symbol 'custom-loads (cons load loads)))))
+ (put symbol 'custom-loads (cons (purecopy load) loads)))))
;;; Initializing.
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))
+ (1-then-2 t)
+ (t nil))))))
(while args
(let ((entry (car args)))
(if (listp entry)
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)
((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)))