help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Need Help defining customizable objects


From: Drew Adams
Subject: RE: Need Help defining customizable objects
Date: Wed, 13 Jun 2012 14:48:47 -0700

> I need to setup a customizable system where the user can insert,
> delete and set a series of "accounts", one account being a (editable)
> name, and a fixed-size (5) list of key-values, and only the value
> would be editable.

I understand that description to specify something like this value:

(("account1" (key1 "value1")
             (key2 "value2")
             (key3 "value3")
             (key4 "value4")
             (key5 "value5"))
 ("account2" (key1 "foo1")
             (key2 "foo2")
             (key3 "foo3")
             (key4 "foo4")
             (key5 "foo5"))
 ...)

Where the strings but not the keys are user modifiable, and the user can define
any number of accounts (including none).

Here, each item in the list is an account; the car of an account is its
(editable) name; the cdr is a list of 5 pairs, the car of each pair being one of
the five predefined, constant keys (in the same order), and the cadr being an
(editable) value for that key.

But you do not say what the 5 possible keys are.  And you do not say whether
their order is constant (imposed).

> I did my homework, read the manual and related pages
> (http://original.jamesthornton.com/emacs/elisp/chapter/elisp_14.html)
> and been playing with custom definitions all morning but so far I
> could only muster this :
> 
> (defcustom mail-bug-accounts '(("host" "")
>                   ("port" "")
>                   ("box" "")
>                   ("icon" ""))
>   "Alist of mail-bug-accounts."
>   :type '(alist :value-type (repeat string))
>   :group 'mail-bug)


But there you show a completely different kind of value as the default (it does
not fit your description above, AFAICT):

'(("host" "") ("port" "") ("box" "") ("icon" ""))

1. Where is the editable account name? I see only the key/value pairs.

2. I see only 4 (not 5) key/value pairs.

3. I guess these are the (first 4?) keys: "host", "port", "box", "icon".  Is
that right?  What's the fifth one?

4. Are the keys always in fact in that order?

5. Why not use symbols instead of strings for the keys, especially if the user
cannot edit their names?


In sum, the first step is to define clearly what you want, and to give an
example (e.g. a default value) that fits that definition.


The second step is defining the defcustom.  For that, this info might help:

a. You can use type `string' for an editable field.

b. You can use :tag to change the label the user sees for a given part.

c. Use `list', not `repeat', for a list with fixed length and fixed item type.

d. Use `repeat' for a list of unlimited length.

If the key order is rigid, then the keys need to be constants in the type
declaration.  Here is a list of 5 items, each of which is a list of a key and a
value, the value part being editable and the key part being constant:

E.g. (list (list (const key1) (string :tag "Key1 Value"))
           (list (const key2) (string :tag "Key2 Value"))
           (list (const key3) (string :tag "Key3 Value"))
           (list (const key4) (string :tag "Key4 Value"))
           (list (const key5) (string :tag "Key5 Value")))

If the key order is not rigid, then the keys need to be chosen from the 5 that
are possible, so you can use a `choice' instead of listing five key-value items.

But I know of no easy way to ensure, using choice, that you get an overall value
that has each of the keys exactly once (instead of, say, a given key being used
more than once).

You can do pretty much anything you need, but you might need to end up using
`restricted-sexp' as the type and toughing it out using :match-alternatives.
The first step is to come up with a simple design.  The last step is to
implement it using defcustom.  I get the feeling you are still on step 1.

Here is a defcustom that corresponds to what I thought you were describing at
the beginning:

(defcustom foo '(("account1"
                  (key1 "value1")
                  (key2 "value2")
                  (key3 "value3")
                  (key4 "value4")
                  (key5 "value5")))
  "The inimitable foo."
  :type '(repeat (list
                  (string :tag "Account")
                  (list (const key1) (string :tag "Key1 Value"))
                  (list (const key2) (string :tag "Key2 Value"))
                  (list (const key3) (string :tag "Key3 Value"))
                  (list (const key4) (string :tag "Key4 Value"))
                  (list (const key5) (string :tag "Key5 Value")))))

> A list where the user can insert, delete and set key-values, but not
> accounts, so basically it's the opposite of what I want. Also the keys
> are called "keys", when I'd like to name them.
> 
> How can I produce a (editable : ins, del, set) list of 
> (non-fully-editable) lists?

Use `repeat' for ins, del.

> Bonus question : Once the user sets a few of those "account" objects,
> how will they be sorted, and is there a way to sort them ?

You can sort them in your code that uses them.  Or you can sort them
automatically whenever the option is set, using keyword :set.

But you need not sort by keys if you use the approach above, which requires each
of the keys in the order specified.  The user will not be able to customize to
get a value that has the keys in the wrong order.

HTH.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]