[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

45. "Querying the User"

.setq query-chapter chapter-number

The following functions provide a convenient and consistent interface for asking questions of the user. Questions are printed and the answers are read on the stream query-io, which normally is synonymous with terminal-io but can be rebound to another stream for special applications.

We will first describe two simple functions for yes-or-no questions, then the more general function on which all querying is built.

Function: y-or-n-p &optional message stream
This is used for asking the user a question whose answer is either "yes" or "no". It types out message (if any), reads a one-character answer, echoes it as "Yes" or "No", and returns t if the answer is "yes" or nil if the answer is "no". The characters which mean "yes" are Y, T, space, and hand-up. The characters which mean "no" are N, rubout, and hand-down. If any other character is typed, the function will beep and demand a "Y or N" answer.

If the message argument is supplied, it will be printed on a fresh line (using the :fresh-line stream operation). Otherwise the caller is assumed to have printed the message already. If you want a question mark and/or a space at the end of the message, you must put it there yourself; y-or-n-p will not add it. stream defaults to the value of query-io.

y-or-n-p should only be used for questions which the user knows are coming. If the user is not going to be anticipating the question (e.g. if the question is "Do you really want to delete all of your files?" out of the blue) then y-or-n-p should not be used, because the user might type ahead a T, Y, N, space, or rubout, and therefore accidentally answer the question. In such cases, use yes-or-no-p.

Function: yes-or-no-p &optional message stream
This is used for asking the user a question whose answer is either "Yes" or "No". It types out message (if any), beeps, and reads in a line from the keyboard. If the line is the string "Yes", it returns t. If the line is "No", it returns nil. (Case is ignored, as are leading and trailing spaces and tabs.) If the input line is anything else, yes-or-no-p beeps and demands a "yes" or "no" answer.

If the message argument is supplied, it will be printed on a fresh line (using the :fresh-line stream operation). Otherwise the caller is assumed to have printed the message already. If you want a question mark and/or a space at the end of the message, you must put it there yourself; yes-or-no-p will not add it. stream defaults to the value of query-io.

To allow the user to answer a yes-or-no question with a single character, use y-or-n-p. yes-or-no-p should be used for unanticipated or momentous questions; this is why it beeps and why it requires several keystrokes to answer it.

Function: fquery options format-string &rest format-args
Asks a question, printed by (format query-io format-string format-args...), and returns the answer. fquery takes care of checking for valid answers, reprinting the question when the user clears the screen, giving help, and so forth.

options is a list of alternating keywords and values, used to select among a variety of features. Most callers will have a constant list which they pass as options (rather than consing up a list whose contents varies). The keywords allowed are:

.kitem :type What type of answer is expected. The currently-defined types are :tyi (a single character) and :readline (a line terminated by a carriage return). :tyi is the default. .kitem :choices Defines the allowed answers. The allowed forms of choices are complicated and explained below. The default is the same set of choices as the y-or-n-p function (see above). Note that the :type and :choices options should be consistent with each other. .kitem :list-choices If t, the allowed choices are listed (in parentheses) after the question. The default is t; supplying nil causes the choices not to be listed unless the user tries to give an answer which is not one of the allowed choices. .kitem :help-function Specifies a function to be called if the user hits the HELP key. The default help-function simply lists the available choices. Specifying nil disables special treatment of HELP. Specifying a function of three arguments--the stream, the list of choices, and the type-function--allows smarter help processing. The type-function is the internal form of the :type option and can usually be ignored. .kitem :condition If non-nil, a condition to be signalled before asking the question. The handler of this condition may supply an answer, in which case the user is not asked. The details are given below. The default condition is :fquery. .kitem :fresh-line If t, query-io is advanced to a fresh line before asking the question. If nil, the question is printed wherever the cursor was left by previous typeout. The default is t. .kitem :beep If t, fquery beeps to attract the user's attention to the question. The default is nil, which means not to beep unless the user tries to give an answer which is not one of the allowed choices. .kitem :clear-input If t, fquery throws away type-ahead before reading the user's response to the question. Use this for unexpected questions. The default is nil, which means not to throw away typeahead unless the user tries to give an answer which is not one of the allowed choices. In that case, typeahead is discarded since the user probably wasn't expecting the question. .kitem :select If t and query-io is a visible window, that window is temporarily selected while the question is being asked. The default is nil. .kitem :make-complete If t and query-io is a typeout-window, the window is "made complete" after the question has been answered. This tells the system that the contents of the window are no longer useful. Refer to the window system documentation for further explanation. The default is t.

The argument to the :choices option is a list each of whose elements is a choice. The cdr of a choice is a list of the user inputs which correspond to that choice. These should be characters for :type :tyi or strings for :type :readline. The car of a choice is either a symbol which fquery should return if the user answers with that choice, or a list whose first element is such a symbol and whose second element is the string to be echoed when the user selects the choice. In the former case nothing is echoed. In most cases :type :readline would use the first format, since the user's input has already been echoed, and :type :tyi would use the second format, since the input has not been echoed and furthermore is a single character, which would not be mnemonic to see on the display.

Perhaps this can be clarified by example. The yes-or-no-p function uses this list of choices:
 
((t "Yes") (nil "No"))
and the y-or-n-p function uses this list:
 
(((t "Yes.") #/y #/t #\sp #\hand-up)
 ((nil "No.") #/n #\rubout #\hand-down))

If a condition is specified (or allowed to default to :fquery), before asking the question fquery will signal the condition. (See (condition) for information about conditions.) The handler will receive four arguments: the condition name, the options argument to fquery, the format-string argument to fquery, and the list of format-args arguments to fquery. As usual with conditions, if the handler returns nil the operation proceeds as if there had been no handler. If the handler returns two values, t and ans, fquery will immediately return ans. No conventions have yet been defined for standard condition names for use with fquery.

If you want to use the formatted output functions instead of format to produce the promting message, write
 
(fquery options (format:outfmt exp-or-string exp-or-string ...))
format:outfmt puts the output into a list of a string, which makes format print it exactly as is. There is no need to supply additional arguments to the fquery unless it signals a condition. In that case the arguments might be passed so that the condition handler can see them. The condition handler will receive a list containing one string, the message, as its third argument instead of just a string. If this argument is passed along to format, all the right things happen.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Brad Parker on June, 13 2006 using texi2html