Subject: bug#38785: 26.3; `y-or-n-p' leaves prompt and response in echo area

From: Drew Adams <[email-masked]>
Date: Sat, 28 Dec 2019 14:55:08 -0800 (PST)

`y-or-n-p' puts its prompt in the echo area.

[Aside: That is not ideal for a prompt.  Some other interaction might be
better, such as using a pop-up for the prompt.  In any case, `y-or-n-p'
and similar functions should NOT use the minibuffer.  `read-key' should
continue to act without any use of the minibuffer.  IMHO, it would make
zero sense to use the minibuffer to read a key.]

At the end, `y-or-n-p' puts its prompt in the echo area again, followed
by the user's response (`y' or `n'):

 (unless noninteractive (message "%s%c" prompt (if ret ?y ?n)))

This is a bother, and it can confuse users, especially when there are
additional questions that follow the `y-or-n-p' prompting.

For example, consider a `y-or-n-p' followed by a `map-y-or-n-p'.  When
the latter is finished, the prompt from the preceding `y-or-n-p' gets
restored to the echo area.  That makes little sense, and it can be quite
confusing.

`map-y-or-n-p' does not leave any of its prompts in the echo area.  This
is a good thing, not a bad thing.  Instead, as a good citizen, it does
this at the end, to ensure that it hasn't left any of its echo-area
prompts behind, as litter:

 ;; Clear the last prompt from the minibuffer, and restore the
 ;; previous echo-area message, if any.
 (let ((message-log-max nil))
   (if msg (message "%s" msg) (message "")))

Perhaps that, or similar, is what `y-or-n-p' should do.

Presumably the reason that `y-or-n-p' does what it does is to provide
feedback of the char (`y' or `n') that you typed.  It's true that that's
helpful, but it also causes problems (see above).

Perhaps `y-or-n-p' should do what it does now, but then reset the echo
area after a brief delay (e.g. 1 sec), where "reset" means to do what
`map-y-or-n-p' does: restore any previous echo-area content.  IOW, it's
not bad to echo your response to the `y-or-n-p' question.  But it is bad
not to clean up afterward, leaving the echo area littered with the
prompt.

For example, have `y-or-n-p' bind `msg' to `(current-message)' at the
outset, and then do this at the end:

 (let ((ret (eq answer 'act)))
       (unless noninteractive
         (message "%s%c" prompt (if ret ?y ?n))         ; <==== (1)
         (run-with-timer 1 nil
                         (lambda () 
                           (let ((message-log-max nil)) ; <==== (2)
                             (if msg 
                                 (message "%s" msg)
                               (message ""))))))
       ret)

(1) is what `y-or-n-p' does now, to show you your response.
(2) is what `map-y-or-n-p' does, to clean up after itself.

If something similar to this 1-2 punch is not done, and if the only
available choice is for `y-or-n-p' to do what it does now (#1), or
to just clean up after itself (#2), then my vote is for #2.

In GNU Emacs 26.3 (build 1, x86_64-w64-mingw32)
 of 2019-08-29
Repository revision: 96dd0196c28bc36779584e47fffcca433c9309cd
Windowing system distributor `Microsoft Corp.', version 10.0.17763
Configured using:
 `configure --without-dbus --host=x86_64-w64-mingw32
 --without-compress-install 'CFLAGS=-O2 -static -g3''