8

This question arose from my previous question on emacs beta. In short I want to bind C-; to an Emacs functions in a terminal, but it seems that something captures this key before it reaches Emacs: Emacs thinks I pressed ;.

The obvious suspect is the terminal emulator, but I've checked many of them (xterm, gnome-terminal, terminator, terminology) and none of them works. Most probably I can exclude window manager, because in the GUI version of Emacs, the key C-; works just fine. I tried also two different shells: bash and zsh, but again without success.

What else can I try?

  • According to your question on Emacs, pressing Ctrl+; sends ; to Emacs, so nothing is capturing it, what's happening is that Ctrl+; and bare ; send the same information. Which one is it: capture (i.e. Emacs receives nothing), or loss of information (i.e. Emacs receives ;)? – Gilles Oct 12 '14 at 17:21
  • there is no standard code for C-; in terminal. What happens if you type C-v C-; in plain bash? – artm Oct 12 '14 at 17:33
  • @Gilles I see ; in emacs -nw irrespectively whether I hit ; or C-;. – WeSenseASoulInSearchOfAnswers Oct 12 '14 at 17:43
  • @artm bash just like emacs prints just bare ;. – WeSenseASoulInSearchOfAnswers Oct 12 '14 at 17:45
11

Perhaps your confusion arises from not having used an actual terminal. Back when serious computers were the size of several upright refrigerators, a terminal communicated with a central computer over a serial cable using characters and characters only. The characters were part of some standardized character set, e.g. ASCII or EBCDIC, but typically ASCII. ASCII has 33 control characters and the terminal operator sent them by pressing a special key (such as DEL) or by holding down the CTRL key and pressing another key. The central computer only saw the resulting control character; it did not know what keys were pressed to produce the character.

A terminal emulation program such as xterm mimics that behavior. The terminal emulator provides a way to send all 33 ASCII control characters and Emacs will receive those characters if they are sent. But Emacs is like the central computer in the above description--- it has no way of knowing what keys were actually pressed when you run it under a terminal emulator. So if you press CTRL and semicolon, unless the terminal emulation program has mapped those keypresses to some ASCII character, Emacs will not know that anything has been typed.

Terminal emulators typically use the following mappings to generate control characters:

keypress       ASCII
--------------------
ESCAPE          27
DELETE          127
BACKSPACE       8
CTRL+SPACE      0
CTRL+@          0
CTRL+A          1
CTRL+B          2
CTRL+C          3
etc...
CTRL+X          24
CTRL+Y          25
CTRL+Z          26
CTRL+[          27
CTRL+\          28
CTRL+]          29
CTRL+^          30
CTRL+_          31

Note that CTRL+; does not appear in that list. Terminals will usually just send the printable character assigned to key if CTRL+key isn't mapped to a control character. So what your terminal emulator is telling you by sending ; alone is that it doesn't know what to do when you press CTRL+;.

All this applies only if you're using a terminal or a terminal emulation program. If you're running Emacs as a native application under some window system, then Emacs has full access to the keystroke events and not just characters. So Emacs can see that you pressed CTRL and semicolon together and allow you to assign an action to that keystroke pair.

Terminals often have function keys and arrow keys that also generate sequences of characters that include control characters. These sequences typically begin with ASCII code 27 (ESCAPE).

3

Terminals transmit characters (more precisely: bytes), not keys. When you press a key or a keychord like Ctrl+;, this information has to be encoded into a sequence of bytes. Keychords that represent a character, like A or Shift+A or À, are sent as that character: a, A, à (the last one being one or two bytes depending on the terminal's character encoding).

Keychords involving function keys have no corresponding character, so they are sent as escape sequences: a sequence of bytes beginning with the escape character (\e in an Emacs string, appearing as cyan ^[ if entered literally in a buffer). A few function keys have corresponding bytes which are control characters.

The keychord Ctrl+; has no standard escape sequence, so most terminal emulators generate the character ;. This loses the information that the Ctrl modifier was pressed.

In order to define a binding for Ctrl+;, you'll need to configure your terminal emulator to send a different escape sequence. I don't think you can do this with Gnome terminal (Gnome is rarely configurable). You can do it with Xterm. See Are there any linux terminals which can handle all key combinations? for instructions.

The shell that you may run in the terminal is not involved. A GUI Emacs has no problem because the GUI (X11) transmits input events in a form that encodes keys and modifiers, not as a mere sequence of characters.

See How do keyboard input and text output work? for more detailed background on how input gets from your keyboard to your application.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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