What I've done, and I really need to find a way to get it opened, is write my very own wrapper around GetOpt::Long. What it does is multi-step:
- It accepts parameters from the rest of the code - these parameters do not need to be passed in all at once, but the "accept parameter" function can be called multiple times. This allows me to load all my modules, and each module can register what options it wants to accept with the global wrapper.
- It then takes the parameters, puts them together in a way that GetOpt::Long will like, and calls GetOpt::Long to do the actual option parsing.
- It then calls any call-backs that were initially registered for extra validation. Sure, you can tell GetOpt that you want an integer. But this allows you to put in a CODE ref that then checks that the value is really between 1 and 12, for example, if you're validating months. The parameter is also passed in such that if the validation assigns back to $_[0], it changes the value which is useful when you want to be able to have a parameter that is something like --smtp_server AUTO and let the validation code figure out the automatic value. (Not that I have any idea how to do that for an smtp server, but maybe you do have such an idea.)
- It then checks if the -? or --help parm was passed in. If so, it generates the help based on what was given to it. It also will print out the default values as it knows them, prints out all the variations (e.g., a parameter of 'v|verbose!' would have -v, --verbose, --noverbose as valid options - this would automatically be part of the help), and then exits.
The parameters are just a list of hashes which have keys for name, default, validate, help, and maybe others I don't recall. Except for name, the rest can be code refs or strings.
This setup has saved us countless weeks of development time over the last 4 years or so. I am positive that it has saved us multiple weeks of development time just in the last 6 months.