Function: read-answer

read-answer is a byte-compiled function defined in map-ynp.el.gz.

Signature

(read-answer QUESTION ANSWERS)

Documentation

Read an answer either as a complete word or its character abbreviation.

Ask user a question and accept an answer from the list of possible answers.

QUESTION should end in a space; this function adds a list of answers to it.

ANSWERS is an alist with elements in the following format:
  (LONG-ANSWER SHORT-ANSWER HELP-MESSAGE)
where
  LONG-ANSWER is a complete answer,
  SHORT-ANSWER is an abbreviated one-character answer,
  HELP-MESSAGE is a string describing the meaning of the answer.

SHORT-ANSWER is not necessarily a single character answer. It can be also a function key like F1, a character event such as C-M-h, or a control character like C-h.

Example:
  '(("yes" ?y "perform the action")
    ("no" ?n "skip to the next")
    ("all" ?! "accept all remaining without more questions")
    ("help" ?h "show help")
    ("quit" ?q "exit"))

When read-answer-short is non-nil, accept short answers.

Return a long answer even in case of accepting short ones.

When use-dialog-box is t, pop up a dialog window to get user input.

View in manual

Probably introduced at or before Emacs version 26.2.

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/map-ynp.el.gz
(defun read-answer (question answers)
  "Read an answer either as a complete word or its character abbreviation.
Ask user a question and accept an answer from the list of possible answers.

QUESTION should end in a space; this function adds a list of answers to it.

ANSWERS is an alist with elements in the following format:
  (LONG-ANSWER SHORT-ANSWER HELP-MESSAGE)
where
  LONG-ANSWER is a complete answer,
  SHORT-ANSWER is an abbreviated one-character answer,
  HELP-MESSAGE is a string describing the meaning of the answer.

SHORT-ANSWER is not necessarily a single character answer.  It can be
also a function key like F1, a character event such as C-M-h, or
a control character like C-h.

Example:
  \\='((\"yes\"  ?y \"perform the action\")
    (\"no\"   ?n \"skip to the next\")
    (\"all\"  ?! \"accept all remaining without more questions\")
    (\"help\" ?h \"show help\")
    (\"quit\" ?q \"exit\"))

When `read-answer-short' is non-nil, accept short answers.

Return a long answer even in case of accepting short ones.

When `use-dialog-box' is t, pop up a dialog window to get user input."
  (let* ((short (if (eq read-answer-short 'auto)
                    (or use-short-answers
                        (eq (symbol-function 'yes-or-no-p) 'y-or-n-p))
                  read-answer-short))
         (answers-with-help
          (if (assoc "help" answers)
              answers
            (append answers '(("help" ?? "show this help message")))))
         (answers-without-help
          (assoc-delete-all "help" (copy-alist answers-with-help)))
         (prompt
          (format "%s(%s) " question
                  (mapconcat (lambda (a)
                               (if short
                                   (if (characterp (nth 1 a))
                                       (format "%c" (nth 1 a))
                                     (key-description (nth 1 a)))
                                 (nth 0 a)))
                             answers-with-help ", ")))
         (message
          (format "Please answer %s."
                  (mapconcat (lambda (a)
                               (format "`%s'" (if short
                                                  (if (characterp (nth 1 a))
                                                      (string (nth 1 a))
                                                    (key-description (nth 1 a)))
                                                (nth 0 a))))
                             answers-with-help " or ")))
         (short-answer-map
          (when short
            (or (gethash answers read-answer-map--memoize)
                (puthash answers
                         (let ((map (make-sparse-keymap)))
                           (set-keymap-parent map minibuffer-local-map)
                           (dolist (a answers-with-help)
                             (define-key map (if (characterp (nth 1 a))
                                                 (vector (nth 1 a))
                                               (nth 1 a))
                               (lambda ()
                                 (interactive)
                                 (delete-minibuffer-contents)
                                 (insert (nth 0 a))
                                 (exit-minibuffer))))
                           (define-key map [remap self-insert-command]
                             (lambda ()
                               (interactive)
                               (delete-minibuffer-contents)
                               (beep)
                               (message message)
                               (sit-for 2)))
                           map)
                         read-answer-map--memoize))))
         answer)
    (while (not (assoc (setq answer (downcase
                                     (cond
                                      ((and (display-popup-menus-p)
                                            last-input-event ; not during startup
                                            (listp last-nonmenu-event)
                                            use-dialog-box)
                                       (x-popup-dialog
                                        t
                                        (cons question
                                              (mapcar (lambda (a)
                                                        (cons (capitalize (nth 0 a))
                                                              (nth 0 a)))
                                                      answers-with-help))))
                                      (short
                                       (read-from-minibuffer
                                        prompt nil short-answer-map nil
                                        'read-char-history))
                                      (t
                                       (read-from-minibuffer
                                        prompt nil nil nil
                                        'yes-or-no-p-history)))))
                       answers-without-help))
      (if (string= answer "help")
          (with-help-window "*Help*"
            (with-current-buffer "*Help*"
              (insert "Type:\n"
                      (mapconcat
                       (lambda (a)
                         (format "`%s'%s to %s"
                                 (if short (if (characterp (nth 1 a))
                                               (string (nth 1 a))
                                             (key-description (nth 1 a)))
                                   (nth 0 a))
                                 (if short (format " (%s)" (nth 0 a)) "")
                                 (nth 2 a)))
                       answers-with-help ",\n")
                      ".\n")))
        (beep)
        (message message)
        (sit-for 2)))
    answer))