Bash – Bind Ctrl-\ in inputrc

bashinputrcterminal

I've been futzing around with this and can't seem to get it to work. Using Ctrl+V in the terminal correctly outputs ^\ for this combination so it should be recognizable.

As I have Ctrl+\ bound to suspend-frame in emacs, I would like to be able to quickly get back into the foreground with another press of Ctrl+\.

I believe this is the only viable combination:

"\C-\\": "fg\n"

If I hit Enter after Ctrl+V for this combination, I get the following output, which might be useful:

bash: $'\034': command not found

Best Answer

Ctrl+\ is one of the control characters that cause the terminal to send a signal (SIGQUIT), like Ctrl+C (SIGINT) and Ctrl+Z (SIGTSTP). You can run stty -a to show what characters have a special meaning to the terminal; see Clear / erase a mistyped invisible password on a shell / terminal in Linux for more details. The upshot is that when you press Ctrl+\, bash doesn't see a character on its standard input, it sees a signal, and that doesn't go through the key bindings mechanisms.

You can switch off the meaning for the character in the terminal with the command stty quit undef. If you do that, bash will see the character as input and your key binding will take effect.

To arrange for Ctrl+\ to be a bash binding but have its normal terminal binding when running a command, change the terminal settings before and after running a command.

preexec () {
  stty quit '^\'
}
precmd () {
  stty quit undef
}

preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`HISTTIMEFORMAT= history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//"`;
    preexec "$this_command"
}
trap 'preexec_invoke_exec' DEBUG
PROMPT_COMMAND='precmd'

Rather than make the key type fg and a newline, bind the key to a shell command. You can't do that from .inputrc, which applies to all readline applications, not just to bash. Instead, define a bash binding in your .bashrc:

bind -x '"\C-\\": "fg"'
Related Question