2

When selecting items from the menu-bar, then the echo area echoes the selected menu item.

Test this by selecting menu-bar -> file -> new window below, when you clicked this menu-bar item, then the echo area states: menu-bar file new-window-below.
(I will call this echoes in the text below)

This is unfortunate because sometimes a menu-bar item puts a prompt at the minibuffer. The prompt gets overwritten by this silly echoes. And I scratch my head why nothing is happening.

I could disable those echoes by setting echo-keystrokes to zero (setq echo-keystrokes 0). But then I can't see started but unfinished keystrokes messages (like C-x-) anymore.

Is there any solution to this dilemma?

Note: this filter aproach did not help.

Reproduction:

The following Elisp snippet adds a menu item Menu Bar Fun to the Help menu.

If echo-keystrokes is set to 0 the prompt is shown when the user is expected to input a character.

If echo-keystrokes is set to 1 the prompt Character: is overwritten by the echo of the menu key sequence.

(defun my-menu-bar-fun (something)
  "Simulating a menu-bar function reading something."
  (interactive "cCharacter: ")
  (message "The thing was: %s" something))

(require 'easymenu)
(easy-menu-add-item menu-bar-help-menu nil ["Menu Bar Fun" my-menu-bar-fun t])

2 Answers 2

2

This is not a real answer but it describes the current situation. (I hope I got it right.)

The following section of keyboard.c is relevant for the mouse event messages:

  /* If in middle of key sequence and minibuffer not active,
     start echoing if enough time elapses.  */

  if (minibuf_level == 0
      && !end_time
      && !current_kboard->immediate_echo
      && (this_command_key_count > 0
      || !NILP (call0 (Qinternal_echo_keystrokes_prefix)))
      && ! noninteractive
      && echo_keystrokes_p ()
      && (/* No message.  */
      NILP (echo_area_buffer[0])
      /* Or empty message.  */
      || (BUF_BEG (XBUFFER (echo_area_buffer[0]))
          == BUF_Z (XBUFFER (echo_area_buffer[0])))
      /* Or already echoing from same kboard.  */
      || (echo_kboard && ok_to_echo_at_next_pause == echo_kboard)
      /* Or not echoing before and echoing allowed.  */
      || (!echo_kboard && ok_to_echo_at_next_pause)))
    {
      /* After a mouse event, start echoing right away.
     This is because we are probably about to display a menu,
     and we don't want to delay before doing so.  */
      if (EVENT_HAS_PARAMETERS (prev_event))
        echo_now ();

It shows that the menu key sequences are echoed even more direct than normal key strokes. The timer that ticks for normal keystrokes is bypassed for menu key sequences. BTW, echo_keystrokes_p() just tests whether echo-keystrokes is positive.

Now let us have a look at echo_now() which is also defined in keyboard.c:

/* Display the current echo string, and begin echoing if not already
   doing so.  */

static void
echo_now (void)
{
  if (!current_kboard->immediate_echo
      /* This test breaks calls that use `echo_now' to display the echo_prompt.
         && echo_keystrokes_p () */)
    {
      current_kboard->immediate_echo = true;
      echo_update ();
      /* Put a dash at the end to invite the user to type more.  */
      echo_dash ();
    }

  echoing = true;
  /* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak).  */
  message3_nolog (KVAR (current_kboard, echo_string));

Most interesting is here the last comment. That comment explicitly states that advising message has no effect. That is the reason why the filter approach does not work. Furthermore, it shows that the developers already considered to make message filters work. If you deliver them one more good reason to do so maybe they will.

Finally, let us have a look at the Elisp function read-key in subr.el:

(defun read-key (&optional prompt)
  "Read a key from the keyboard.
Contrary to `read-event' this will not return a raw event but instead will
obey the input decoding and translations usually done by `read-key-sequence'.
So escape sequences and keyboard encoding are taken into account.
When there's an ambiguity because the key looks like the prefix of
some sort of escape sequence, the ambiguity is resolved via `read-key-delay'."
  ;; This overriding-terminal-local-map binding also happens to
  ;; disable quail's input methods, so although read-key-sequence
  ;; always inherits the input method, in practice read-key does not
  ;; inherit the input method (at least not if it's based on quail).
  (let ((overriding-terminal-local-map nil)
        (overriding-local-map read-key-empty-map)
        (echo-keystrokes 0)
        ...

Later on they read the actual key with read-key-sequence-vector within the body of the let-form.

The last let-binding (echo-keystrokes 0) is the most interesting part. Locally let-binding echo-keystrokes to zero is the official way to suppress the echoing of keystrokes including menu key sequences while reading characters from the keyboard.

Pityingly, the interactive special form does not take that measure.

It is also not possible to advice interactive in any way since it is a special Elisp form:-(.

4
  • Good investigation. We shouldn't have to advise anything, ideally. A variable (which code can bind etc.) is better. (Personally I favor user options for such things, and I don't mind the possibility that code can bind an option, but that's not the official policy.)
    – Drew
    Commented Mar 22, 2019 at 23:56
  • @Drew In my point of view for the question at hand the missing handling of echo-keystrokes in interactive is the actual bug that should even really be reported as bug and not as feature request.
    – Tobias
    Commented Mar 22, 2019 at 23:59
  • That's for discussion (e.g. in a bug/enhancement thread). As one user, I'd prefer to separate (1) echoing keystrokes (which is incremental, starts only after a user-controllable delay, and proceeds only as long as the typed keys do not form a complete key sequence), on the one hand, and (2) immediately echoing complete menu items that have been chosen. Those are different actions, for different purposes. IOW, I don't think I want echo-keystrokes to control both, unless it can do allow all possible combinations. But it's worth discussing, at least.
    – Drew
    Commented Mar 23, 2019 at 0:04
  • Thank you for the detailed research! I'll keep the question open, though, because I can't solve this problem.
    – jue
    Commented Mar 25, 2019 at 14:35
1

You can set or bind variable echo-keystrokes to 0 (zero) to prevent, well, echoing keystrokes (which includes menu actions). C-h v echo-keystrokes says:

echo-keystrokes is a variable defined in C source code.

Its value is 1

Documentation:

Nonzero means echo unfinished commands after this many seconds of pause.

The value may be integer or floating point. If the value is zero, don't echo at all.

You can customize this variable.

This user option is documented in the Emacs manual, node Display Custom, and in the Elisp manual, node Echo Area Customization.


But the question explicitly asks about echoing (complete) menu-item choices, and not echoing of prefix keys (partial key sequences), so the above info doesn't really answer the question.

I don't know how to suppress such menu-choice echoing. It doesn't seem to be documented. If you don't get a good answer here then consider posing the question at [email protected] or even filing an enhancement request: M-x report-emacs-bug.

From the answer by @Tobias, what you request is confirmed as impossible currently. Please consider asking for it using M-x report-emacs-bug.

7
  • But then I can't see unfinished keystrokes like C-x- anymore. I described this in the later part of my question.
    – jue
    Commented Mar 22, 2019 at 15:27
  • Yes, sorry; I don't know how to suppress such menu-choice echoing. It doesn't' seem to be documented. If you don't get a good answer here then consider posing the question at [email protected] or even filing an enhancement request: M-x report-emacs-bug.
    – Drew
    Commented Mar 22, 2019 at 20:41
  • Hi Drew, I think your comment is the actual valuable answer here. It is the statement from the expert that selectively switching off the messages from menu key sequences is not possible as far as he knows. When I saw this question I planned to have a look at the C-sources. I want to see how close the coupling between the key sequences and the messages is. A good catch for that is echo-keystrokes. But, I am not so experienced with the C-sources of Emacs. So let us see what happens
    – Tobias
    Commented Mar 22, 2019 at 21:26
  • @tobias: I've incorporated my comment and yours into the answer, in that case. If you can cite "the expert" etc. in another answer that would be good. (Comments themselves can be removed at any time.) If this isn't possible then it sounds like an enhancement request is called for.
    – Drew
    Commented Mar 22, 2019 at 23:50
  • @Drew 1st: Incorporate all comments as necessary. I am fine with that. 2nd: Please see my answer. There is an explicit statement in the C-code that they wanted to use the symbol message for key-strokes. They wanted to support Emacs-Speak with that. Emacs Speak should be able to advise message.
    – Tobias
    Commented Mar 22, 2019 at 23:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.