[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
:CHOOSE-MULTIPLE functionality of TV:CHOOSE-VARIABLE-VALUES
Date: Fri, 15 Sep 89 09:42:00 cdt
From: bcsaic!HUNTSAI!rodney@beaver.cs.washington.edu (Rodney Daughtrey)
Anyone know how or have a way to implement the functionality of the
:CHOOSE-MULTIPLE option to TV:CHOOSE-VARIABLE-VALUES in an analogous
DW facility (such as DW:ACCEPT-VALUES, DW:ACCEPT-VARIABLE-VALUES, etc)?
What's the cleanest/most elegant solution?
The closest thing seems to be the SUBSET presentation type. It doesn't
provide a way to specify a displayed form of each item distinct from the
item itself, but this is easy enough to do in your own code after ACCEPT
returns the strings. Here's a simple function that does it:
(defun choose-multiple (alist &rest accept-options)
(let ((result (apply #'accept `((subset .,(mapcar #'car alist))) accept-options)))
(mapcar #'(lambda (item) (cdr (assoc item alist))) result)))
(dw:accepting-values (*query-io*)
(choose-multiple '(("Foo" . :foo) ("Bar" . :bar) ("Baz" . :baz))
:prompt "Enter"))
Enter: 1Foo0 Bar 1Baz
0<ABORT> aborts, <END> uses these values
(:BAZ :FOO)
The only problem with this is specifying the default, since the SUBSET
presentation type is comparing the elements of the :DEFAULT list to the
elements of the set using EQL, and you don't get EQL string when you
type a similar string. You can work around it by using #n= and #n#, but
here's a version that handles :DEFAULT specially, allowing you to
specify the items rather than the strings:
(defun choose-multiple (alist &rest accept-options
&key (default nil default-p) &allow-other-keys)
(flet ((inverse-map-keywords (keywords)
(mapcar #'(lambda (item) (car (rassoc item alist))) keywords)))
(when default-p
(setq default (inverse-map-keywords default)))
(let ((result (apply #'accept `((subset .,(mapcar #'car alist)))
(append (and default-p `(:default ,default))
accept-options))))
(mapcar #'(lambda (item) (cdr (assoc item alist))) result))))
(dw:accepting-values (*query-io*)
(choose-multiple '(("Foo" . :foo) ("Bar" . :bar) ("Baz" . :baz))
:prompt "Enter" :default '(:foo :baz)))
It probably wouldn't be too hard to implement this as a new presentation
type.
barmar