The following code shows how to define an accept for a structure (instance) with several fields. That accept is then used within another similar accept call.
A presentation type called
ticket
is defined. The
accept
method has two recursive calls to
accept
, one to read the name of a candidate for president and another to read the name of the running mate. We provide two possible
accept
methods; in order to compare them, you will have to compile first one and then the other. The first reads the two names separated by a comma on the same line. The second reads the two names on separate lines, delimited by
RETURN
. They both do completion within the field. That is, if you do
(accept 'ticket :stream win)
with the first
accept
method, and type
"Bu,Qu<RETURN>
", the screen appearance will be
"Bush,Quayle"
and the return value will be
(BUSH QUAYLE)
.
If you use the second accept method and type:
"Cl
Go
"
"Clinton
Gore"
and the return value will be
(CLINTON GORE)
.
This example also demonstrates simple cross-field constraints by insisting that the two candidates be of the same party.
For key implementation details, read the comments in the code.
(in-package :clim-user)
(define-presentation-type ticket ())
(setf (get 'bush 'party) 'republican)
(setf (get 'quayle 'party) 'republican)
(setf (get 'clinton 'party) 'democrat)
(setf (get 'gore 'party) 'democrat)
;;; separated by comma version
(define-presentation-method accept ((type ticket) stream view &key &allow-other-keys)
(declare (ignore view))
(let ((president (accept '(member bush clinton) :stream stream :prompt nil
;; add comma as a completing delimiter
:blip-characters '(#,))))
;; Make sure that the names were separated by a comma
(unless (eql (read-gesture :stream stream) #,)
(simple-parse-error "Ticket members must be separated by commas"))
(let ((veep (accept '(member quayle gore) :stream stream :prompt nil)))
;; Validate party affiliations
(unless (eql (get president 'party) (get veep 'party))
(simple-parse-error "Ticket members must be of the same party"))
(list president veep))))
;;; Separated by Return version
(define-presentation-method accept ((type ticket) stream view &key
&allow-other-keys)
(declare (ignore view))
(let ((president (accept '(member bush clinton) :stream stream :prompt nil
;; Remove Newline from activation characters
:activation-characters `()
;; Add Newline as a delimiter, so that we get
;; completion and move-to-next-field behavior
;; when Return is typed.
:blip-characters `(#\Return #\Newline))))
(unless (eql (read-gesture :stream stream) #\Newline)
(simple-parse-error
"Ticket members must be entered on separate lines"))
(let ((veep (accept '(member quayle gore) :stream stream :prompt nil)))
;; Validate party affiliations
(unless (eql (get president 'party) (get veep 'party))
(simple-parse-error "Ticket members must be of the same party"))
(list president veep))))