;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: 4Querying the User* =Text: 3QUERYING THE USER* 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 2*query-io**, which normally is synonymous with 2*terminal-io** but can be rebound to another stream for special applications. The macro 2with-timeout* (see 4(PROCESSES-1)The Scheduler*) can be used with the functions in this chapter to assume an answer if the user does not respond in a fixed period of time. We first describe two simple functions for yes-or-no questions, then the more general function on which all querying is built. 3y-or-n-p* &optional 1format-string* &rest 1format-args* This is used for asking the user a question whose answer is either `y' for `yes' or `n' for `no'. It prints a message by passing 1format-string* and 1format-args* to 2format*, reads a one-character answer, echoes it as `2Yes*' or `2No*', and returns 2t* if the answer is `yes' or 2nil* if the answer is `no'. The characters which mean `yes' are `Y', `T', 2Space*, and 2Hand-up*. The characters which mean "no" are `N', 2Rubout*, and 2Hand-down*. If any other character is typed, the function beeps and demands a `Y or N' answer. You should include a question mark and a space at the end of the message. 2y-or-n-p* does type `(Y or N)' for you. 2*query-io** is used for all input and output. 2y-or-n-p* should be used only for questions that 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 2y-or-n-p* should not be used, because the user might type ahead a `T', `Y', `N', 2Space*, or 2Rubout*, and therefore accidentally answer the question. In such cases, use 2yes-or-no-p*. 3yes-or-no-p* &optional 1format-string* &rest 1format-args* This is used for asking the user a question whose answer is either `yes' or `no'. It prints a message by passing 1format-string* and 1format-args* to 2format*, beeps, and reads in a line from 2*query-io**. If the line is `yes', it returns 2t*. If the line is `no', it returns 2nil*. (Case is ignored, as are leading and trailing spaces and tabs.) If the input line is anything else, 2yes-or-no-p* beeps and demands a `yes or no' answer. You should include a question mark and a space at the end of the message. 2yes-or-no-p* does type `(Yes or No)' for you. 2*query-io** is used for all input and output. To allow the user to answer a yes-or-no question with a single character, use 2y-or-n-p*. 2yes-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. 3fquery* 1options* 1format-string* &rest 1format-args* Asks a question, printed by 2(format *query-io* 1format-string* 1format-args*...)*, and returns the answer. 2fquery* takes care of checking for valid answers, reprinting the question when the user clears the screen, giving help, and so forth. 1options* is a list of alternating keywords and values, used to select among a variety of features. Most callers pass a constant list as the 1options* (rather than consing up a list whose contents varies). The keywords allowed are: 2:type* What type of answer is expected. The currently-defined types are 2:tyi* (a single character), 2:readline* or 2:mini-buffer-or-readline* (a line terminated by a carriage return). 2:tyi* is the default. 2:mini-buffer-or-readline* is nearly the same as 2:readline*, the only difference being that the former uses a minibuffer if used inside the editor. 2: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 2y-or-n-p* function (see above). Note that the 2:type* and 2:choices* options should be consistent with each other. 2:list-choices* If 2t*, the allowed choices are listed (in parentheses) after the question. The default is 2t*; supplying 2nil* causes the choices not to be listed unless the user tries to give an answer which is not one of the allowed choices. 2:help-function* Specifies a function to be called if the user hits the 2Help* key. The default help-function simply lists the available choices. Specifying 2nil* disables special treatment of 2Help*. 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 2:type* option and can usually be ignored. 2:condition* If non-2nil*, a signal name (see 4(DEBUGGING-2)Creating Condition Instances*) to be signaled before asking the question. A condition handler may handle the condition, specifying an answer for 2fquery* to return, in which case the user is not asked. The details are given below. The default signal name is 2:fquery*, which signals condition name 2:fquery*. 2:fresh-line* If 2t*, 2*query-io** is advanced to a fresh line before asking the question. If 2nil*, the question is printed wherever the cursor was left by previous typeout. The default is 2t*. 2:beep* If 2t*, 2fquery* beeps to attract the user's attention to the question. The default is 2nil*, which means not to beep unless the user tries to give an answer which is not one of the allowed choices. 2:stream* The value should be either an I/O stream or a symbol or expression that will evaluate to one. 2fquery* uses the specified stream instead of 2*query-io** for all its input and output. 2:clear-input* If 2t*, 2fquery* throws away type-ahead before reading the user's response to the question. Use this for unexpected questions. The default is 2nil*, which means not to throw away type-ahead unless the user tries to give an answer which is not one of the allowed choices. In that case, type-ahead is discarded since the user probably wasn't expecting the question. 2:make-complete* If 2t* and 2*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 2t*. The argument to the 2:choices* option is a list each of whose elements is a 1choice*. The cdr of a choice is a list of the user inputs which correspond to that choice. These should be characters for 2:type :tyi* or strings for 2:type :readline*. The car of a choice is either a symbol which 2fquery* 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 2:type :readline* would use the first format, since the user's input has already been echoed, and 2: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. A choice can also be the symbol 2:any*. If used, it must be the last choice. It means that any input is allowed, and should simply be returned as a string or character if it does not match any of the other choices. Perhaps this can be clarified by example. The 2yes-or-no-p* function uses this list of choices: 3((t "Yes") (nil "No"))* and the 2y-or-n-p* function uses this list: 3(((t "Yes.") #\y #\t #\space #\hand-up)* 3 ((nil "No.") #\n #\rubout #\hand-down))* If a signal name is specified (or allowed to default to 2:fquery*), before asking the question 2fquery* will signal it. (See 4(DEBUGGING-1)Conditions* for information about conditions.) 2make-condition* will receive, in addition to the signal name, all the arguments given to 2fquery*, including the list of options, the format string, and all the format arguments. 2fquery* provides one proceed type, 2:new-value*, and if a condition handler proceeds, the argument it proceeds with is returned by 2fquery*. If you want to use the formatted output functions instead of 2format* to produce the promting message, write 3(fquery 1options* (format:outfmt 1exp-or-string* 1exp-or-string* ...))* 2format:outfmt* puts the output into a list of a string, which makes 2format* print it exactly as is. There is no need to supply additional arguments to the 2fquery* 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 2format*, all the right things happen. 3fquery* (3condition*) 1Condition* This condition is signaled, by default, by 2fquery*. The condition instance supports these operations: 2:options* Returns the list of options given to 2fquery*. 2:format-string* Returns the format string given to 2fquery*. 2:format-args* Returns the list of additional args for format, given to 2fquery*. One proceed type is provided, 2:new-value*. It should be used with a single argument, which will be returned by 2fquery* in lieue of asking the user. 3format:y-or-n-p-options* 1Constant* A suitable list to pass as the first argument to 2fquery* to make it behave like 2y-or-n-p*. 3format:yes-or-no-p-options* 1Constant* A suitable list to pass as the first argument to 2fquery* to make it behave like 2yes-or-no-p*. 3format:y-or-n-p-choices* 1Constant* A list which 2y-or-n-p* uses as the value of the 2:choices* option.