I hate writing abstraction code like this, but I'm hoping it will be useful.
Details in the README file.