1

I've looked on google, stack exchange, GNU emacs manual, xterm manual, etc. and still haven't found an answer that satisfies my problem(s).

Problem:
Using Systems: Ubuntu 16.04, xterm, emacs-nox
I want to bind the keys Ctrl+i Ctrl+m Ctrl+[ and Meta+Shift+o to any command I want.
But the problem seems to be that all of said key sequences are bound to:
Tab, Return, Escape, and Control Code ESC 0 respectively becuase that's just the way terminals work.

So how do I keep the functionality of the Tab, Return, and Escape whilst having said keybinds at my disposal?
Do I have to remap the keys in the terminal somehow? If so, how?
I will do anything to make this work.

John DeBord
  • 550
  • 3
  • 13

1 Answers1

2

If you want to be fiddly then you can (mostly) do it. For instance, for C-i and C-m, add to your .Xresources:

XTerm*VT100.Translations: #override \
     Ctrl       <KeyPress> I: string("^[OJ") \n\
     Ctrl       <KeyPress> M: string("^[OK")

where ^[ needs to be replaced by the escape character, entered (in emacs) with C-q ESC (C-q runs quoted-insert which inserts the next character literally). The actual escape character can't be displayed in the browser, so I'm using the string ^[ to represent it, as that's how it's typically displayed. \n\ is needed at the end of each line that is continued.

^[OJ and ^[OK were chosen as these sequences seemed to be free. (You can determine which sequences are "free" by inspecting input-decode-map within Emacs, via C-h v input-decode-map RET. The map is effectively a "tree". The numerical values are the codes of the corresponding characters — for instance O is 79. You can determine the code of the letter O by evaluating ?O etc.)

Load the .Xresources with xrdb -load .Xresources and restart your xterms.

In your init.el add:

(define-key key-translation-map (kbd "^[OJ") (whatever-you-want-1))
(define-key key-translation-map (kbd "^[OK") (whatever-you-want-2))

where again ^[ needs to be replaced by the escape character. Replace (whatever-you-want-[12]) appropriately.

For some more details see:

https://kb.iu.edu/d/abko

https://superuser.com/questions/453993/xterm-key-translations

https://manpages.debian.org/stretch/xterm/xterm.1.en.html#Default_Key_Bindings

aplaice
  • 2,126
  • 17
  • 23
  • It's not working for me :/ A couple things are happening: 1) When I did `xrdb -load .Xresources` and restarted my xterm it like inverted my colors making the background white and text black (I haven't changed the default colors of the terminal); and made strings (in between " ") invisible within emacs. 2) When I did `(define-key key-translation-map (kbd "^[OJ") 'previous-line)` all emacs does is spit out the string `"^[OJ` in the buffer. – John DeBord Apr 07 '18 at 05:22
  • Update: The first issue seems to be unrelated; when I log out and log back in the terminal colors are back to normal. – John DeBord Apr 07 '18 at 05:38
  • Update: I think I understand what you meant: I tried `(define-key key-translation-map (kbd "^[OJ") (kbd ""))` and then `(global-set-key (kbd "") 'previous-line)` but it still spits out "`^[OJ`" in the buffer. – John DeBord Apr 07 '18 at 05:47
  • Update: Quick question: How do I inspect the `input-decode-map`. I apologize I'm definitely a noob. – John DeBord Apr 07 '18 at 05:51
  • 1
    Update: When I describe the key in emacs using `Ctrl-h k` for `Ctrl-i` the description is: `^ runs the command self-insert-command, which is an interactive built-in function in 'C source code'. It is bound to many ordinary text characters.` Not sure if this is a clue or not. – John DeBord Apr 07 '18 at 06:51
  • Last Update: So essentially `XTerm*VT100.Translations` is interpreting the input escape sequence and then spitting out the string of the given escape sequence. Should't we be translating the input escape sequence to another escape sequence and not a string? This is the conclusion I've come to. – John DeBord Apr 07 '18 at 07:04
  • Sorry for being too brief. I've slightly updated the answer. – aplaice Apr 07 '18 at 08:37
  • Regarding the last two updates: yes we should be asking XTerm to translate the escape sequence to another escape sequence. Did you enter the character `^[` manually (with `C-q ESC`) or did you copy-paste the code? The actual Escape character can't be displayed in the browser, so copy-pasting `^[` will have the wrong result. (Again, sorry for not being clear enough.) – aplaice Apr 07 '18 at 08:40
  • Ohh ok that makes total sense now! – John DeBord Apr 07 '18 at 19:18
  • This works very well. But what I'm not understanding is how you chose the sequence `^[OJ` and `^[OK`. I'm looking through the `input-decode-map` and I can't really make any sense of it. How did you come to that conclusion? – John DeBord Apr 07 '18 at 19:39
  • Lastly, translating to `""` doesn't seem like a very good idea to me, what would you translate it to if you were in my shoes? – John DeBord Apr 07 '18 at 19:48
  • The format of keymaps is described well in the [info manual](https://www.gnu.org/software/emacs/manual/html_node/elisp/Format-of-Keymaps.html). I picked `^[OJ` as the nested sequence 27 → 79 → 74 (the codes of `^[`, `O` and `J` respectively), was not present, unlike for instance 27 → 79 → 83 (corresponding to ``) and similarly for `^[OK`. You determine the numerical code corresponding to a character with `?{character}` and the character given the code with `(insert {number})` (or just look it up in an ASCII table). – aplaice Apr 07 '18 at 20:43
  • Would, say, `""`, `""` work? – aplaice Apr 07 '18 at 20:44
  • Ok I understand now. So can you just make up – John DeBord Apr 07 '18 at 22:33
  • Ok I understand now. So in my 27 -> 79 keymap the following are taken: `83, 82, 81, 69, 77, 70, 66, 67, 65, 68, 72`. Does this mean that I can translate to any other number I want except for these? And are an unlimited number of `""` keys? I feel like I'm understanding everything, except the limits of what you can and can't do (i.e. the numbers to choose). – John DeBord Apr 07 '18 at 22:39
  • 1
    Yes, any number other than those taken could be used. Regarding the `"<>"` syntax, it seems after testing (but I can't easily find anything in the documentation), that you can use an arbitrary string (even `""`) — so you could just use the non-standard, but descriptive `""` etc. It appears to work and I don't think it would break anything. (One issue that might come up in the future is if you start using a terminal emulator other than xterm — since they have different translation maps — but it's independent of the choice of the `"<>"` key names.) – aplaice Apr 08 '18 at 08:30
  • Do you think there's a way for defining a translation that doesn't output a string? Like for example I have this: `Ctrl ~Meta ~Shift A: string("^[JDA")` But every time I press it in the terminal it outputs the string `DA` Do you know of a way to prevent it from outputting that string? – John DeBord Apr 10 '18 at 21:14
  • Like for example why is `^C` outputted as a string to the terminal but `^A` is not? – John DeBord Apr 10 '18 at 21:20
  • With `"^[JDA"` I think that the issue is that this is interpreted by emacs as `M-j D A` and since `M-j` (unlike, say `M-o`, `C-x` or `C-c`) is not a prefix-key, it's immediately executed, presumably not allowing for any further translation etc. Also, if you plan on using many more XTerm translations, I'd recommend going "deeper" (i.e. just use longer strings — I'm not sure if there's a maximum length on either the XTerm or the emacs side) rather than "wider" (using many different strings), as it's less likely to result in collisions with existing bindings. – aplaice Apr 10 '18 at 22:29
  • Ok I didn't know that. But my fault I don't think I explained myself that well. So what I mean is that the binding `Ctrl ~Meta ~Shift A: string("^[JDA")` works perfectly fine within emacs. But when I'm using that bind in the terminal (outside of emacs) it will spit out the string `DA`. And this poses an annoyance to me, because if I accidently press that keybind, it spits out that string, and then I have to delete it (note for the sake of brevity I have multiple translations like this, so it wouldn't just be this one bind). – John DeBord Apr 10 '18 at 23:53
  • Please move your conversation into chat. Comments are not the right venue to have an extended conversation. – Dan Apr 11 '18 at 00:06
  • @Dan Where's the chat? – John DeBord Apr 11 '18 at 00:17
  • Cool @Dan. Was just about to have my problem fully solved, after three days of working on it. – John DeBord Apr 11 '18 at 04:00
  • 1
    Regarding interpreting the translated bindings in bash — I don't think there's any simple solution. You could try to use the `bind` bash command (e.g. `bind '"\eOJ": ""'` where `\e` is the escape character (yes, different conventions in different programs, for the same character, are annoying...) and `""` is deliberately the empty string — see the [info manual](https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html) for details), but things are likely to start getting very brittle. As for moving the conversation to chat, I'm not certain how to do that. – aplaice Apr 11 '18 at 13:33
  • FWIW I've created a new chat room [here](https://chat.stackexchange.com/rooms/75839/keybinds-on-xterm-and-emacs-nox). – aplaice Apr 11 '18 at 13:34
  • That works perfectly! – John DeBord Apr 12 '18 at 06:34