Design: Metatool
So... When building stuff, I keep finding this pattern where I have a 'system' that actually has a number of executables and I would really prefer to have a front-end CLI. It turns out that it's not a terribly difficult problem to solve once and for all, you just have to know the trick.
It's looking at argv[0] to know how the program was invoked.
No, really, that's it.
Finding the binary
OK, so there are a few more wrinkles, but that's the tricky bit.
For example, in order to fit the meta tool to existing projects
that just happen to be structured appropriately, we should
probably accept both file name extensions, and handle multiple
hyphenated words. Oh, and an environment variable to an
alternate PATH.
FOO_PATH=/usr/local/lib/foo:/home/user/.bin
foo bar baz would then match foo-bar-baz in either path in
$FOO_PATH or any in $PATH. Or foo-bar-baz.exe. Underscore
should probably be accepted as well as hyphen, so foo_bar.sh
would be invoked with "baz" as its first argument.
At this point, it's easy to feel how it would grow. Configs are another hassle that could be dealt with once for most systems projects. It'd be nice to not have to deal with the hierarchy of configs, but still get that rich system, user, project, environment variable, options hierarchy, right?
Again, following in the footsteps of git, aliases would be next. Aliases work by defining a name and a replacement is used to abbreviate commands, and to set parameters.
I think the way I'd want this to happen, would be a
refactoring of git, so that the main git binary looks at
argv[0] and just uses that name throughout, and all the
version control-specific things it does would be move out of it.
It would be nice, because git is already widely installed, and
it would make it even more useful. That's extremely unlikely to
happen, not least of which is that it's a bit questionable to
change the capabilities of an existing tool that way.
OK, but we can still build it, right?
Well, yes, but it turns out the devil is in the details, so it's not quite as simple as it looks.
Parameters
The hierarchy of parameters.
- System config
- User global config
- Project config
- Environment variables
- CLI args
Environment variables would be munged according to some system. Here's from Kafka:
.=>_-=>____=>__
The next problem is how to make these available in a
more-or-less uniform way. We can probably munge something into
env vars, but the weird corner cases keep on coming. For a
simple example, what to do with repeated long-opts? --fnord
can definitely be rendered as FOO_FNORD, but do you do if
there are three of them? Perhaps the answer is to have sensible
defaults, and to leave it to a top-level configuration to
control this.