3

I want to write a defcustom definition for a variable my-var.

my-var is an alist that maps strings to plists. Each such plists maps one of three keys (:x, :y, :z) to a list of strings. So, a member of my-var could be:

'("key" . (:x '("a" "b") :y '("c") :z '("d")))

So I want the use to be able to provide a string to be a key of the my-var alist, and lists of strings as value for the three keys of the plist.

The problem is I don't know how to do that. Specifically, I don't know where to put the :option keyword to offer :x, :y and :z as possible keys:

:type '(alist :key-type string
              :value-type (plist :key-type symbol
                                 :value-type (repeat string)))
3
  • 1
    Good question. Not enough good questions here about specifying types for defcustom, IMO.
    – Drew
    Dec 10, 2022 at 2:53
  • Yeah, it's one of the very few cases with Emacs where I think the documentation could be a bit clearer/richer...
    – efl
    Dec 10, 2022 at 5:11
  • The doc could be better, but more importantly the Customize UI could be better. And the customize code is too complex.
    – Drew
    Dec 10, 2022 at 5:15

1 Answer 1

3

I think this is what you're describing:

(defcustom myvar ()
  "..."
  :group 'mygroup
  :type '(alist :key-type string
                :value-type (plist :key-type symbol
                                   :options (:x :y :z)
                                   :value-type (repeat string))))

(You can also omit :key-type symbol, for the plist, as the type is symbol by default.)

I assume you don't really want to quote the values in the plist. That is, I assume that this is an alist element that you want to allow:

("key1" :x ("a" "b") :z ("q"))

and not this:

("key1" :x '("a" "b") :z '("q"))

aka not this:

("key1" :x (quote ("a" "b")) :z (quote ("q")))

By the way, you can also use a restricted-sexp to specify that the plist keys must be keywords, not just any symbols. Here's an example:

(defcustom myvar '(("key1"))
  "..."
  :group 'emacs
  :type '(alist :key-type (string :tag "Alist key (string):")
            :value-type
        (plist :key-type
               (restricted-sexp :match-alternatives (keywordp)
                    :tag "Plist key (keyword)")
                       :options (:x :y :z)
                       :value-type (repeat string))))

However, I seem to have discovered a bug when you try to do that and also give it a nil default value. I've filed Emacs bug #59937 for that now.

1
  • Yes! Excellent, that's what I needed. And yes, the quotes shouldn't be there. Thank you!
    – efl
    Dec 10, 2022 at 5:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.