7

I am using emacs from a remote ssh session. So I ssh remote in a terminal and launch it from there with emacs.

When I set the following key binding

(global-set-key (kbd "M-[") 'backward-paragraph)

And I press keys starting with <f5> to <f12>, I get weird characters printed. For example pressing <f5> prints 15~ and also move cursor in some location.

1 Answer 1

14

You’re in complicated territory.

A terminal emulator listens for key events from the operating system, and translates them into characters. It then sends those characters to the running application (which in this case is Emacs, but the terminal doesn’t know or care what application it is).

There are used to be a lot of different terminals in the world, and most of them were incompatible with each other. Exactly how they translated key events into characters was one of the incompatible things about them. In the modern era of terminal emulators, we mostly emulate the VT100, plus sometimes features from later terminals such as the VT220 or VT420. You don’t say what terminal emulator you are using, but in practice most of them just default to doing whatever xterm does. You can read in excrutiating detail exactly what xterm does, but I will try to summarize.

By default, xterm pretends that your Alt key is a Meta key, and then does what the VT100 did, which is to translate any key press with a Meta modifier into an escape character followed by the modified key. Thus M-a becomes 0x1b 0x41, M-b becomes 0x1b 0x42, and so on. It follows then that M-[ must be 0x1b 0x5b. So far this is not complicated.

So what happens for the function keys? There is no character that corresponds to the F5 key directly, so it has to be translated into some sequence of bytes. Here is the relevant table from that document I linked to:

Key        Escape Sequence
---------+-----------------
F1       | SS3 P
F2       | SS3 Q
F3       | SS3 R
F4       | SS3 S
F5       | CSI 1 5 ~
F6       | CSI 1 7 ~
F7       | CSI 1 8 ~
F8       | CSI 1 9 ~
F9       | CSI 2 0 ~
F10      | CSI 2 1 ~
F11      | CSI 2 3 ~
F12      | CSI 2 4 ~

SS3 and CSI are of course defined way earlier in the document:

…
ESC O
     Single Shift Select of G3 Character Set (SS3  is 0x8f), VT220.
     This affects next character only.
…
ESC [
     Control Sequence Introducer (CSI  is 0x9b).
…

So anywhere the document says that it sends SS3, it is really going to send an escape followed by an “O”, or 0x1b 0x4f. And any time it says that it will send CSI, it will actually send an escape followed by an “[”, or 0x1b 0x5b.

You may now begin to see the problem.

Every time you hit <f5>, your terminal sends the bytes 0x1b 0x5b 0x31 0x35 0x7E. The first two bytes trigger your key binding, moving the cursor backwards by a paragraph. The the next three bytes all invoke self-insert-command and type their corresponding character, inserting a 15~ into the buffer.

In fact, Emacs already had something bound to M-[. When Emacs starts up inside of a terminal it puts a key map there that handles all of the interesting escape sequences that it might receive, so that your arrow keys and function keys and whatnot will work.

4
  • wow amazing explanation. I am wondering if you have used clippety package when I use after-init hook, i get run-hooks: Autoloading failed to define function global-clippety-mode and it also messes up some function keys
    – phoxd
    Sep 29, 2021 at 0:24
  • 1
    Thank you. I’ve never used clippety, so I don’t know how it could fail. You might ask a separate question about that, or ask clippety’s author for support by opening an issue. Perhaps you have an outdated version that doesn’t include global-clippety-mode? or maybe there is some other error message prior to that one?
    – db48x
    Sep 29, 2021 at 0:40
  • 1
    +1 - great answer!
    – NickD
    Sep 29, 2021 at 0:45
  • 2
    Apparently, I misspelled clipetty
    – phoxd
    Sep 29, 2021 at 5:25

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.