2

I have this tester code:

(defvar dbg-vec nil)
(defun foobar ()
  (interactive)
  (message "%S" (setq dbg-vec (this-command-keys-vector))))
(set-transient-map '(keymap (left . foobar)
                     (t . foobar)
                     (97 . foobar)))

It works as expected in the GUI. But for emacs -nw it gives strange behavior. If I press left after evaling the last statement, I get:

  • error "No previous locations for find-tag invocation"
  • dbg-vec becomes [27], although the key code for left is 113.

Note that it still works as expected if I press a. What could be the source of this error and how can I fix it?

4
  • In emacs -nw keys like the arrow send a sequence of key strokes. In the case of "left" ESC [ D is emitted. Mar 31 '15 at 11:23
  • OK, I could run that through input-decode-map myself, if set-transient-map doesn't want to do this automatically. But how do I access ESC [ D? As you see, I only got ESC (27).
    – abo-abo
    Mar 31 '15 at 11:29
  • I think you only get ESC because your keymap is removed once that has been handled. One way to do this is to use the KEEP-PRED parameter which will make stay active a bit longer. Another would be to hook yourself into another keymap that is handled after input-decode-map (depending on what you are trying to do, of course). Mar 31 '15 at 11:43
  • Or, you can try to add a nested entry for ESC [ D using something like (27 . (?[ . (?D . foobar))). Mar 31 '15 at 12:08
1

The right fix is to not use a catchall t binding. These are very tricky to use and basically can't be made 100% reliable.

The whole motivation behind set-transient-map was actually to avoid using t bindings (which are typically used to exit from some transient mode, so they just take the event and then want to "unread" it by putting it on unread-command-event but "unreading" can't be done reliably).

3
  • Thanks, but I'm using t just to issue the warning and throw away the input, so there's no problem with un-reading. The issue is that binding left is different in GUI and -nw versions. But only if t is set.
    – abo-abo
    Mar 31 '15 at 14:07
  • As I said, such catch-all bindings are tricky to use, and this SO question is just another proof of it. Throwing away a random event is not simple because it can be part of a sequence of events, such that dropping the first changes the meaning/effect of the subsequent ones.
    – Stefan
    Apr 1 '15 at 3:22
  • OK, I've worked out a way to do what I want without t. But now I have to use my own function instead of set-transient-map. And I have to port that function to all recent Emacs versions.
    – abo-abo
    Apr 1 '15 at 7:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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