[Top][All Lists]

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

diff-list: customizing lists

From: Alex Schroeder
Subject: diff-list: customizing lists
Date: Tue, 04 Dec 2001 21:07:12 +0100
User-agent: Gnus/5.090004 (Oort Gnus v0.04) Emacs/21.1 (i686-pc-linux-gnu)

Per Abrahamsen <address@hidden> writes:

>> It didn't get "blessed" by Per, but perhaps it still is a starting
>> point for other people?
> As far as I remember, the API was my only real remaining complain.
> I think you should post it here and get feedback from Bades, Monnier
> and Love.  I get cranky about code I have written, especially
> something that was as painful to create as customize, and have a
> strong emotional bias against changes not made by me.  So please don't
> wait for me to bless anything, the best I can do is to praise by faint
> condemnations.

The following two pages are taken from the Emacs Wiki.  They reflect
pretty much the discussion we had at the time on customizing lists.


Sometimes there are defcustoms for lists with decent default
values. People customize them, adding a few entries. Now what happens
when the maintainers change the default value? The people that
customized their variables are out of luck. They will have to review
the changes carefully.

This page presents solutions that allow lisp authors to offer defcustoms that
will add elements to the standard value without overwriting it.

Very Simple List Without Add-To-List Effect

Here's an example which will be rewritten below. The current custom type will
not allow users to specify additions only.

 (defcustom mm-automatic-display
   '("text/plain" "text/enriched" "text/richtext" "text/html"
     "text/x-vcard" "image/.*" "message/delivery-status" "multipart/.*"
     "message/rfc822" "text/x-patch" "application/pgp-signature"
     "application/emacs-lisp" "application/x-pkcs7-signature"
     "application/pkcs7-signature" "application/x-pkcs7-mime"
   "A list of MIME types to be displayed automatically."
   :type '(repeat string)
   :group 'mime-display)


 From: Simon Josefsson
 Subject: Re: changed default values
 To: Per Abrahamsen
 CC: (MailingList for Emacs Custom)
 Date: Mon, 10 Sep 2001 13:53:54 +0200

This implement my other idea, of only storing the difference between the
default value in .emacs. It doesn't require modifications in custom or
elsewhere, but something like this could be used by e.g. Gnus.

 (defvar mm-automatic-display-default '("text/plain"
                                        "text/enriched" "text/richtext"))

 (defun jas-custom-set (symbol value)
   (let (res)
     (dolist (val value)
       (if (not (member val (symbol-value (intern (concat (symbol-name symbol) 
           (push (cons val t) res)))
     (dolist (val (symbol-value (intern (concat (symbol-name symbol) 
       (if (not (member val value))
           (push (cons val nil) res)))
     (set-default symbol res)))

 (defun jas-custom-get (symbol)
   (let ((res (symbol-value (intern (concat (symbol-name symbol) "-default")))))
     (dolist (val (symbol-value symbol))
       (if (cdr val)
           (setq res (append res (list (car val))))
         (setq res (delete (car val) res))))

 (defcustom mm-automatic-display 'nil
   "A list of MIME types to be displayed automatically."
   :group 'mime-display
   :type '(repeat string)
   :set 'jas-custom-set
   :get 'jas-custom-get)

and in code where you want to know the value of `mm-automatic-display' you
insert `(jas-custom-get 'mm-automatic-display)'. This step could probably be
hidden by clever programming as well.

Storing Additions and Removals when Saving

In this solution, additions and removals are stored in a property which is used
to modify the standard value everytime the variable is changed via custom.

In code where you want to know the value of `mm-automatic-display', you could
just use the variable itself.

 (require 'cl)

 (defun custom-diff-list-apply (symbol value)
   "Return VALUE for diff-lists.
 If VALUE is a list starting with the symbol DIFF-LIST,
 it must have the form (DIFF-LIST ADDITIONS REMOVALS).
 In that case, the standard value of SYMBOL is used.
 All elements of ADDITIONS are added and all elements
 of REMOVALS are removed.
 In all other cases, VALUE is returned."
   (if (and (listp value)
            (> (length value) 2)
            (eq 'diff-list (nth 0 value)))
       (let ((additions (reverse (nth 1 value)))
             (removals (nth 2  value))
             (result (copy-list (eval (car (get symbol 'standard-value))))))
         (dolist (item removals)
           (setq result (remove item result)))
         (dolist (item additions)
           (setq result (cons item result)))

 (defun custom-set-diff-list (symbol value)
   "Set SYMBOL to VALUE for diff-lists.
 See `custom-diff-list-apply'."
   (put symbol 'diff-list (list value))
   (set-default symbol (custom-diff-list-apply symbol value))
   (message "Set %S to %S, prop to %S" symbol (default-value symbol) (get 
symbol 'diff-list)))

 (defun custom-get-diff-list (symbol)
   "Returns SYMBOL's DIFF-LIST property.
 It is stored there by `custom-set-diff-list'."
   (let ((diff-list (get symbol 'diff-list)))
     (or (car diff-list) (symbol-value diff-list))))

 ;; Example

 (defcustom mm-automatic-display
   '("text/plain" "text/enriched" "text/richtext" "text/html"
     "text/x-vcard" "image/.*" "message/delivery-status" "multipart/.*"
     "message/rfc822" "text/x-patch" "application/pgp-signature")
   "A list of MIME types to be displayed automatically."
   :type '(choice (repeat :tag "Edit saved value" string)
                  (list :tag "Modify the standard value"
                        (const :tag "Add and remove selected entries" diff-list)
                        (repeat :tag "Additions" string) 
                        (repeat :tag "Removals"  string)))
   :initialize 'custom-initialize-reset
   :set 'custom-set-diff-list
   :get 'custom-get-diff-list
   :group 'mime-display)


Suppose your code offers a variable holding a long list of entries. Users may
add to this list using custom. Once they save their changes, however, the
entire list will be saved. If you change the standard value in a later release
of your package, these users will never see this -- or they will have to merge
their saved list with the new standard list manually.

You need to implement a diff-list. A diff-list is like a normal list, but with
a crucial difference: You specify which entries to delete from the standard
value, and you specify which entries to add to the standard value. This will be
saved into your users ~/.emacs file. The standard value itself is not saved.

Here's how it will look like in a custom buffer (I am using
mm-automatic-display from Gnus as an example):

Mm Automatic Display: [Hide] [Value Menu] Modify the standard value:
Add to and remove from the standard value
Items to add to the standard value:
[INS] [DEL] Regexp: alex
[INS] [DEL] Regexp: barbarella
Items to remove from the standard value:
[X] text/plain
[X] text/enriched
[X] text/richtext
[X] text/html
[X] text/x-vcard
[ ] image/.*
[ ] message/delivery-status
[ ] multipart/.*
[ ] message/rfc822
[ ] text/x-patch
[ ] application/pgp-signature
   [State]: you have edited the value as text, but you have not set the option.
A list of MIME types to be displayed automatically.
Parent groups: [Mime Display]

Instead of saving the complete list:

 '("alex" "barbarella" "image/.*" "message/delivery-status" ...)

The additions and removales themselves will be saved in your .emacs file:

 '(diff-list ("alex" "barbarella") ("text/plain" "text/enriched" ...))

reply via email to

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