Turn the codebase into a library with a thin executable.

I also mistakenly didn't commit earlier code that added supports for
empty patterns, so unfortunately this big refactor includes that as well.