4

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.

Tobias
  • 32,569
  • 1
  • 34
  • 75
  • (1) *"This should be a quite common need for library developers."* No, I don't think it is. (2) Does the code you show in your update not do the job? It's the kind of thing I would have tried (using `put` with `standard-value`). The question isn't clear to me in this sense: What is wrong with what you tried - where does it go wrong, or what is the difficulty? So far, it looks like a good question and an answer together. What am I missing? As a *question* (including that update), it's now *unclear* (to me, at least). I don't know whether to upvote or vote to close. ;-) – Drew Dec 19 '21 at 23:29
  • @Drew (1) I felt the need when I added that `dvisvgm`-option to Preview-LaTeX. Adding options to existing libraries that are written in an extensible way is a good thing. It should be easy for library developers. (2) So far I know, the code does the job, but it is based on reverse-engineering. It shouldn't. I added a clarification about that at the end of the question. – Tobias Dec 20 '21 at 04:50
  • Thanks for the explanations. For #1, I guess you're not revising the library itself, right? (Have you tried asking the maintainer to do what you want?) It's still not clear to me what the use case is. If you define your own library that loads the original one, you can just redefine the `defcustom` there, unless the original is preloaded. (I'm assuming you really need to change that `defcustom` instead of defining your own option.) But however you do it, won't users of the original `defcustom` expect/want its original behavior? Sorry, as you can see, the use case is still not too clear to me. – Drew Dec 20 '21 at 05:00
  • @Drew One should read the full doc;-). I found that part in Section ["Defining Customization Variables"](https://www.gnu.org/software/emacs/manual/html_node/elisp/Variable-Definitions.html#:~:text=standard-value). So maybe, the code does no longer base on undocumented behavior. However, the use is still discouraged in the doc. – Tobias Dec 20 '21 at 05:01
  • @Drew Please have a look at the option [`preview-image-creators`](https://github.com/jwiegley/auctex/blob/9e7406cddd87c1f318d943bd3f5edc73d82e349d/preview/preview.el#L180) of the preview-LaTeX-library. That list is intended for the extension of the library. From my point it is questionable to leave that as an user option since changing it requires heavy plumping. Nevertheless, currently it is an user-option and I have to deal with it. It maps symbols to some functions. The symbols can then be used to select the image type with `preview-image-type`. I wanted to provide `dvisvgm` there. – Tobias Dec 20 '21 at 05:12
  • Please consider adding some of what you explain in comments to the question, to make it more self-contained. Comments can be deleted at any time, and they're not searchable. Thx. – Drew Dec 20 '21 at 16:21
  • In the Info topic you refer to, I see `custom-add-frequent-value`. Doesn't that help with what you want to do? – Drew Dec 20 '21 at 16:47
  • @Drew Thanks for the consideration. But pityingly `custom-add-frequent-value` does not help. It does not help with the standard value of `preview-image-creators` since I want to add a value to the alist and not distinguish one of the existing values as option. It does also not help with the setting of `preview-image-type`, since there the widget type `choice` is used with its own predefined values that are automatically generated from `preview-image-creators`. It is not an alist and not a hook variable. – Tobias Dec 20 '21 at 17:08
  • OK, sorry. I read the description of that option quickly and thought it might be relevant. – Drew Dec 20 '21 at 20:42

0 Answers0