Next Prev Up Top Contents Index

7.1.2 Defining an Accept for a Structure With Several Fields

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
"

the window will contain:

"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))))

CommonLisp Interface Manager 2.0 User's Guide - 8 Aug 2003

Next Prev Up Top Contents Index