I like to use emacs in terminal mode (-nw), but it seems most (all?) terminals can't handle some key combinations - for example, C-<RET> or C-M-%. I know this is because most terminals emulate a VT-100, which didn't have these combinations. Are there any linux terminals (preferably KDE) which can handle these key combinations, or is this a fundamental limitation of all terminals?
- 807,993
- 194
- 1,674
- 2,175
- 222
- 2
- 8
4 Answers
When you press a key or key combination in a terminal, it is transmitted to the application running in the terminal as a sequence of one or more characters. For example, when you press a, the application receives a. When you press Enter, the application receives the character CR (a.k.a. ^M (pronounced “control-emm”), a.k.a. character number 13, a.k.a. \r or \015). Key combinations involving Alt are typically transmitted as the character ESC (a.ka. ^[ a.k.a. \e or \033) followed by the sequence for the key or key combination without Alt. Function keys and other key combinations are transmitted as escape sequences beginning with \e[ or \eO.
The escapes sequences are not fully standardized, and terminals typically ignore certain attributes for certain keys. For example, Ctrl+Shift+letter is often transmitted exactly like Ctrl+letter by default.
You can see what your terminal sends for a key combination by pressing Ctrl+V followed by that key combination in a shell prompt, or C-q or C-h c followed by the key combination in Emacs.
With some terminal emulators, you can configure the escape sequences for each key. On Xterm, this is done through X resources. Most setups read resources from ~/.Xresources when X starts, and you can load the file manually with xrdb -merge ~/.Xresources.
Term.VT100.translations: #override \n\
Ctrl ~Shift ~Meta <key>Return: string("\033[73;5~") \n\
Ctrl Shift ~Meta <key>percent: string("\033[37;6~")
A common convention uses escape sequences of the form ESC [ number1 ; number2 ~ for function keys with modifiers. number1 indicates the function key (15 to 24 for F5 to F12 — for historical reasons, F1 through F4 have different escape sequences) and number2 indicates the modifier (2 for Shift, 3 for Meta, 5 for Ctrl, 7 for Ctrl+Meta, and add 1 for Shift with at least one of Ctrl or Meta).
Emacs translates escape sequences into its internal key representation through input-decode-map or local-function-key-map (or function-key-map before Emacs 23).
(define-key local-function-key-map "\033[73;5~" [(control return)])
(define-key local-function-key-map "\033[37;6~" [(control ?L)])
- 807,993
- 194
- 1,674
- 2,175
-
So, if I understand this correctly, I need to first define an escape sequence in my terminal which corresponds to some key combination. Then, in emacs, I need to map the escape sequence back to the key combination. Can the escape sequence be arbitrary, as long as it doesn't conflict with those defined in `infocmp $TERM`? – Yossarian Jun 17 '13 at 07:11
-
2@Yossarian Yes. In addition to not conflicting, the escape sequences need to be unambiguous, i.e. no escape sequences should be a prefix of another one. This means in practice that the first character has to be `ESC` (unless you want to try some character ≥128, but that will restrict the possible input encodings) and the second character has to be something for which you want no `ESC foo` binding. – Gilles 'SO- stop being evil' Jun 17 '13 at 07:37
-
I've just got round to trying what you suggested. Should `local-set-key` actually be `define-key`? The former gives an error (wrong number of arguments), while the latter works, at least for C-Enter. It seems konsole still has trouble sending C-M-%. – Yossarian Jun 24 '13 at 12:25
-
@Yossarian Indeed, it should be `define-key`. I don't know if Konsole's escape keys can be configured, xterm is probably more customizable than any alternative. – Gilles 'SO- stop being evil' Jun 24 '13 at 14:07
-
2Note that [Thomas Dickey's xterm](http://invisible-island.net/xterm/xterm.html) is under active development. With the `XTerm*modifyOtherKeys: 2` resource it will generate unique sequences even for `C-M-` combinations, but with that setting you will need to provide a lot of custom mappings (`XTerm*modifyOtherKeys: 1` is less capable but far more functional out of the box). For an example (albeit one which didn't work for me) see the `xterm-extras.el` library and the associated `.Xresources` and `.inputrc` files in the [easymacs](http://sourceforge.net/projects/easymacs/) download. – phils Jun 24 '13 at 22:05
-
Cross-referencing with http://stackoverflow.com/a/17267661/324105 – phils Jun 24 '13 at 22:11
-
+1. but references to the provided facts would be quite relevant – Bleeding Fingers Sep 15 '13 at 11:09
-
In my terminal, backspace and ctrl+backspace both give `^?`. Is there any possible way to distinguish between backspace and ctrl+backspace? – trusktr Oct 13 '13 at 15:54
-
@trusktr Maybe. It depends on your terminal emulator. You need to configure your terminal emulator to send different escape sequences. – Gilles 'SO- stop being evil' Oct 13 '13 at 18:57
-
Seems it's not possible with vte terminals yet (Gnome Terminal, Mate Terminal, Guake, etc) as far as I can tell. – trusktr Oct 17 '13 at 19:09
For a limited but significant set of keys, assuming KDE's konsole, one may do the following to have working, complex keybindings in emacs -nw:
I will use my implementation of getting S-<RET> to work as an example:
- Open a new konsole, go to settings -> current profile -> keyboard -> edit
- Hit Add and make a new entry for
Return+Shiftand give it a useful key sequence (I chose\E[27;3which I think is the key sequence sent by X when I was poking around with xev, but that may be wrong -- the important thing to do is make sure that it has a proper escape and doesn't conflict with anything else). - Play with it in the little test area at the bottom to make sure it is working.
- Restart konsole.
Start up
emacs -nwand in the scratch buffer evaluate:(read-key-sequence-vector "Type your new key:")then type your new key combination.
- If you are unfamiliar with this, write the line out, leave the cursor at the end of the line, and hit C-x C-e to get emacs to run that line, it should say to you whatever you put in the quotes and wait for you to type something.
It should spit out a key sequence which you may bind.
(It returned[27 91 50 55 59 51]to me as opposed to the boring old[13]before I messed with the konsole keybinding.)Add to your emacs configuration:
(define-key function-key-map [27 91 50 55 59 51] [(shift return)])I tested it with
emacs -nwin a screen session using:(define-key ess-mode-map [(shift return)] #'ess-eval-line-and-step) (define-key sh-mode-map [(shift return)] #'send-line-to-shell)
- 22,130
- 27
- 68
- 117
- 21
- 1
There are some efforts of extending the VT protocol in a way to allow lossless keyboard input (among other features, such as graphics).
One example is notty: https://github.com/withoutboats/notty
- 1,596
- 15
- 29
The short answer is that it is a fundamental limitation of all terminals.
The slightly longer answer is that even if someone created a terminal that does what you want, Emacs itself would require major changes to work with this hypothetical terminal.
- 81
- 8
-
That's a good point about emacs, that didn't even occur to me. I guess I'll start using the gui instead. – Yossarian Jun 15 '13 at 08:50
-