Bash – Bind C-i and TAB keys to different commands in terminal applications via .inputrc

bashinputrcterminalterminal-emulator

For what I have tried, TAB and C-i in .inputrc seems to mean the same thing, whatever I bind to one is bound to the other. I know that originally, it was the same thing and that this behavior is kind of inherited from the old times but nowadays, apart from terminal emulators, all X applications makes the difference between a C-i and a TAB press.

So is there a way to run a terminal command ("complete" for example) when I press the TAB key and run another command when I press C-i?

(the same question applies for C-m and ENTER, C-z, C-d, and all these control sequences that I would like to send by other means than their original binding and apply my own commands to these precious keybindings)

And by the way, if you could explain a little bit the process from a keypress to a shell interpretation that would help me understand. For now I understood that keyboard events are translated by Xmodmap, then by .inputrc and that the result is interpreted by the shell or something like this.

I am currently using Guake, and sometimes gnome-terminal, as terminal emulators.

After following the link proposed in a comment, it appears that the terminal emulator is the element of the chain that transforms TAB keysym from X server into C-i, and sends it to the bash shell because it doesn't understand such things as TAB, ENTER and siblings. So configuring readline itself won't work as it comes after the terminal emulator and before the bash shell. The question could be then precised like this: How to configure my terminal emulator so it translates TAB and C-i, ENTER and C-m, etc, to different pairs of character sequences? Maybe make TAB and ENTER send a new custom escape sequence, that could be mapped in .inputrc later to the original commands, and finally be able to use C-i and C-m for other purposes. Or leave TAB and ENTER and make C-i and C-m send escape sequences instead.

Best Answer

The terminal emulator translates events like “the Tab key was pressed” into sequences of characters that the application running in the terminal (bash, in your case) reads. See How do keyboard input and text output work? for a more detailed presentation of this topic.

For historical reasons, a few of keys send a character that's the same as pressing Ctrl with some other character: Tab = Ctrl+I, Return = Ctrl+M, Esc = Ctrl+[. This is because historical physical terminals did this, so applications that run in terminals expect it, so terminals do it.

Both Guake and Gnome-terminal use the VTE library, which does not allow the mapping from key chords to character sequences to be configured. You have the same problem as bash - wrong key sequence bindings with control+alt+space

Xterm has fully configurable key bindings. You can make the Tab key send a tab character (that's the default), or make it send the string hello, or whatever you choose. Xterm is configured via X resources. For example, to make Tab send the escape sequence \e[t when pressed and \e]t when released, put this in your ~/.Xresources:

XTerm.vt100.translations: #override \
  <Key>Tab: string("\033[t") \n\
  <KeyRelease>Tab: string("\033]t") \n\

Or maybe you would leave Tab sending the tab character and make Ctrl+I send something else:

XTerm.vt100.translations: #override \
  Ctrl~Meta~Shift<Key>I: string("\033[a5i") \n\
  Ctrl~Meta Shift<Key>I: string("\033[a6i") \n\

You can then bind \e[a5i to whatever you want in bash and other terminal applications with configurable keybindings.

Note that by convention, multi-character escape sequences start with the escape character (often represented as \e or \033 or \x1b in programming languages and configuration files); some applications may have trouble with escape sequences starting with other characters, and of course you can't have a character that's both an escape sequence and a key of its own, unless you're willing to accept a timeout (that's how it works in applications such as vi where Esc on its own is bound to some functionality). If you define your own key sequences, take care not to clash with the ones sent by function and cursor keys, which are more or less de facto standardized.