Function: y-or-n-p

y-or-n-p is a byte-compiled function defined in subr.el.gz.

Signature

(y-or-n-p PROMPT)

Documentation

Ask user a "y or n" question.

Return t if answer is "y" and nil if it is "n".

PROMPT is the string to display to ask the question; y-or-n-p adds " (y or n) " to it. It does not need to end in space, but if it does up to one space will be removed.

If you bind the variable help-form to a non-nil value while calling this function, then pressing help-char causes it to evaluate help-form and display the result. PROMPT is also updated to show help-char like "(y, n or C-h) ", where help-char is automatically bound to help-form-show.

No confirmation of the answer is requested; a single character is enough. SPC also means yes, and DEL means no.

To be precise, this function translates user input into responses by consulting the bindings in query-replace-map; see the documentation of that variable for more information. In this case, the useful bindings are act, skip, recenter, scroll-up, scroll-down, and quit. An act response means yes, and a skip response means no. A quit response means to invoke abort-recursive-edit. If the user enters recenter, scroll-up, or scroll-down responses, perform the requested window recentering or scrolling and ask again.

Under a windowing system a dialog box will be used if last-nonmenu-event is nil and use-dialog-box is non-nil.

By default, this function uses the minibuffer to read the key. If y-or-n-p-use-read-key is non-nil, read-key is used instead (which means that the user can't change buffers (and the like) while y-or-n-p is running).

Probably introduced at or before Emacs version 19.23.

Source Code

;; Defined in /usr/src/emacs/lisp/subr.el.gz
(defun y-or-n-p (prompt)
  "Ask user a \"y or n\" question.
Return t if answer is \"y\" and nil if it is \"n\".

PROMPT is the string to display to ask the question; `y-or-n-p'
adds \" (y or n) \" to it.  It does not need to end in space, but
if it does up to one space will be removed.

If you bind the variable `help-form' to a non-nil value
while calling this function, then pressing `help-char'
causes it to evaluate `help-form' and display the result.
PROMPT is also updated to show `help-char' like \"(y, n or C-h) \",
where `help-char' is automatically bound to `help-form-show'.

No confirmation of the answer is requested; a single character is
enough.  SPC also means yes, and DEL means no.

To be precise, this function translates user input into responses
by consulting the bindings in `query-replace-map'; see the
documentation of that variable for more information.  In this
case, the useful bindings are `act', `skip', `recenter',
`scroll-up', `scroll-down', and `quit'.
An `act' response means yes, and a `skip' response means no.
A `quit' response means to invoke `abort-recursive-edit'.
If the user enters `recenter', `scroll-up', or `scroll-down'
responses, perform the requested window recentering or scrolling
and ask again.

Under a windowing system a dialog box will be used if `last-nonmenu-event'
is nil and `use-dialog-box' is non-nil.

By default, this function uses the minibuffer to read the key.
If `y-or-n-p-use-read-key' is non-nil, `read-key' is used
instead (which means that the user can't change buffers (and the
like) while `y-or-n-p' is running)."
  (let ((answer 'recenter)
	(padded (lambda (prompt &optional dialog)
		  (let ((l (length prompt)))
		    (concat prompt
			    (if (or (zerop l) (eq ?\s (aref prompt (1- l))))
				"" " ")
			    (if dialog ""
                              (if help-form
                                  (format "(y, n or %s) "
                                          (key-description
                                           (vector help-char)))
                                  "(y or n) "
                                  )))))))
    (cond
     (noninteractive
      (setq prompt (funcall padded prompt))
      (let ((temp-prompt prompt))
	(while (not (memq answer '(act skip)))
	  (let ((str (read-string temp-prompt)))
	    (cond ((member str '("y" "Y")) (setq answer 'act))
		  ((member str '("n" "N")) (setq answer 'skip))
		  ((and (member str '("h" "H")) help-form) (print help-form))
		  (t (setq temp-prompt (concat "Please answer y or n.  "
					       prompt))))))))
     ((and (display-popup-menus-p)
           last-input-event             ; not during startup
	   (listp last-nonmenu-event)
	   use-dialog-box)
      (setq prompt (funcall padded prompt t)
	    answer (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip)))))
     (y-or-n-p-use-read-key
      ;; ¡Beware! when I tried to edebug this code, Emacs got into a weird state
      ;; where all the keys were unbound (i.e. it somehow got triggered
      ;; within read-key, apparently).  I had to kill it.
      (setq prompt (funcall padded prompt))
      (while
          (let* ((scroll-actions '(recenter scroll-up scroll-down
                                            scroll-other-window scroll-other-window-down))
                 (key
                  (let ((cursor-in-echo-area t))
                    (when minibuffer-auto-raise
                      (raise-frame (window-frame (minibuffer-window))))
                    (read-key (propertize (if (memq answer scroll-actions)
                                              prompt
                                            (concat "Please answer y or n.  "
                                                    prompt))
                                          'face 'minibuffer-prompt)))))
            (setq answer (lookup-key query-replace-map (vector key) t))
            (cond
             ((memq answer '(skip act)) nil)
             ((eq answer 'recenter)
              (recenter) t)
             ((eq answer 'scroll-up)
              (ignore-errors (scroll-up-command)) t)
             ((eq answer 'scroll-down)
              (ignore-errors (scroll-down-command)) t)
             ((eq answer 'scroll-other-window)
              (ignore-errors (scroll-other-window)) t)
             ((eq answer 'scroll-other-window-down)
              (ignore-errors (scroll-other-window-down)) t)
             ((or (memq answer '(exit-prefix quit)) (eq key ?\e))
              (signal 'quit nil) t)
             (t t)))
        (ding)
        (discard-input)))
     (t
      (setq prompt (funcall padded prompt))
      (defvar empty-history)
      (let* ((empty-history '())
             (enable-recursive-minibuffers t)
             (msg help-form)
             (keymap (let ((map (make-composed-keymap
                                 y-or-n-p-map query-replace-map)))
                       (when help-form
                         ;; Create a new map before modifying
                         (setq map (copy-keymap map))
                         (define-key map (vector help-char)
                           (lambda ()
                             (interactive)
                             (let ((help-form msg)) ; lexically bound msg
                               (help-form-show)))))
                       map))
             ;; Protect this-command when called from pre-command-hook (bug#45029)
             (this-command this-command)
             (str (read-from-minibuffer
                   prompt nil keymap nil
                   (or y-or-n-p-history-variable 'empty-history))))
        (setq answer (if (member str '("y" "Y")) 'act 'skip)))))
    (let ((ret (eq answer 'act)))
      (unless noninteractive
        (message "%s%c" prompt (if ret ?y ?n)))
      ret)))