Assume a library has some customizable option my-option
with a list of values:
(unintern "my-option" obarray)
(defcustom my-option '(first second third)
"Option with a list of values."
:type '(repeat symbol)
:group 'my-group)
(provide 'my-lib)
Further assume that another library extends this list by another value my-additional-val
.
This is not a customization since it is library stuff and not a user setting.
So, my-additional-val
should be added to the standard value of my-option
.
How is this supposed to be done?
This should be a quite common need for library developers.
So there should be some canonical way to do it.
But there is nothing appropriate in the manual. The only thing I came up with until now looks very non-standard:
(with-eval-after-load 'my-lib
(let* ((standard (eval (car (get 'my-option 'standard-value))))
(untouched (equal my-option standard)))
(pushnew 'my-additional-val standard)
(put 'my-option 'standard-value (list
(list
'quote
standard
)))
(when untouched
(setq my-option standard))))
To avoid the XY problem here the background:
I have written a library preview-dvisvgm adding SVG support to preview-latex.
For this library an entry with key dvisvgm
is added as new image creator to the alist of the variable preview-image-creators
of preview-latex
.
I used customize-push-and-save
for that purpose. But that felt wrong since such a modification shows up as customization of preview-image-creators
.
It is not a customization since it is not a user setting. It is an additional image creator provided by a library extending preview-latex
.
Drew proposed in the comments to use (defcustom preview-image-creators ...)
in preview-dvisvgm
before preview
is loaded.
From my point of view that is not the right way since it opposes to the view that preview-dvisvgm
is an extension of preview-latex
. What, if there is another extension library for preview-latex
that tries to do the same? I think adding the new image creator to the already defined standard value of preview-image-creators
is exactly the right thing to do.
UPDATE:
Currently, I use functions like customize-variable-standard-value
and its setter from the following snippet. I would expect functions like that in the custom
library.
(defun customize-variable-standard-value (symbol)
"Return standard value of variable SYMBOL."
(let ((container (get symbol 'standard-value)))
(cl-assert (consp container) "%s does not have a standard value")
(eval (car container))))
(defun customize-set-variable-standard-value (symbol value)
"Set standard value of variable SYMBOL to VALUE."
(let ((standard (customize-variable-standard-value symbol)))
(when (equal (symbol-value symbol) standard)
(set symbol value))
(put symbol 'standard-value (list
(list
'quote
value)))))
(gv-define-simple-setter customize-variable-standard-value customize-set-variable-standard-value)
(with-eval-after-load 'my-lib
(pushnew 'my-additional-val (customize-variable-standard-value 'my-option)))
The problem with this implementation is that it is based on undocumented behavior that might be subject to change. The Elisp-documentation about standard-value
says:
‘customized-value’
‘saved-value’
‘standard-value’
‘theme-value’
These properties are used to record a customizable variable’s
standard value, saved value, customized-but-unsaved value, and
themed values. Do not set them directly; they are managed by
‘defcustom’ and related functions. *Note Variable Definitions::.
Okay, there is more:
Internally, ‘defcustom’ uses the symbol property ‘standard-value’ to record the expression for the standard value, ‘saved-value’ to record the value saved by the user with the customization buffer, and ‘customized-value’ to record the value set by the user with the customization buffer, but not saved. *Note Symbol Properties::. In addition, there’s ‘themed-value’, which is used to record the value set by a theme (*note Custom Themes::). These properties are lists, the car of which is an expression that evaluates to the value.
So maybe, the above implementation is correct. Nevertheless, the direct manipulation of these properties is discouraged. Therefore, it would be nice to have easy getters/setters manipulating the standard value of variables for library programming.