Orsmo has asked for the wisdom of the Perl Monks concerning the following question:

I've recently started work on a new command-line utility, and decided to give Getopt::Declare a try. I've found it to be excellent, but I ran into a seemingly simple problem that just doesn't seem to have a good solution.

The utility is designed to augment and replace an existing utility. As a result, I'm building in support for both the new and old command-line options. Which name is used to call the script will determine which spec is fed to Getopt::Declare. In any event, while I have flexibility in just what the new options will look like, my problem comes from trying to recreate the old ones.

While most of the options are of the '-optionname' variety, there are a number of bare arguments tacked to the end. There are also two forms that the arguments may take:

utility [options] <machinename> [<action>]

or

utility [options] <switchname> <port> [<action>]

In each case the action is one of 'on', 'off', or 'reboot'. Also port is always a positive integer. Thus determining if the first bare argument is a switchname or a machinename becomes relatively trivial based on either the presence of three arguments, or on the fact that the second argument is either numeric or one of the possible actions.

The problem then becomes getting Getopt::Declare to handle these bare options in a sane way, and also getting it's built in usage method to "do the right thing".

Unfortunately, my glance at the code in Getopt/Declare.pm did little to calm my fear that this shiny new tool was going to be able to do what I wanted with bare args.

So I wrote some code (named 'twig' in this case):

#!/usr/local/bin/perl -w ### ### $RCSfile: twig,v $ $Revision: 0.1 $ ### Last modified $Date: 2004/06/30 11:24:30 $ by $Author: Orsmo $ ### use strict; use Getopt::Declare; use File::Basename qw(basename); $::VERSION = do { my @r = (q$Revision: 1.0 $ =~ /\d+/g);sprintf "%d.". +"%02d" x $ #r, @r } my $basename = basename($0); my $specification = qq( [strict] [pvtype: action /on|off|reboot/] -v[erbose] Increase the verbosity of the output. [repeatable] <machine> [<action>] [required] <switchname> <port> [<action:action>] [required] [mutex: <machinename> <switchname> ] ); my $getopt = new Getopt::Declare $specification;

There is, of course, more code than this in my utility, but this is all that is required to illustrate my problems with Getopt::Declare.

Specifically, I get the following for the output of 'twig -help':

Usage: twig [options] <switchname> <port> [<action>] <machine> [<act +ion>] twig -help twig -version Options: -v[erbose] Increase the verbosity of the output.

I expected a usage that looked more like this:

Usage: twig [options] <switchname> <port> [<action>] twig [options] <machine> [<action>] twig -help twig -version Options: -v[erbose] Increase the verbosity of the output.

Moreover, the utility is perfectly willing to take, for example, two arguments, the second of which need not match either :+i or /on|off|reboot/. It is perfectly happy to be called 'twig machinename switchname'. Clearly something is wrong.

I have tried many permutations involving 'mutex' and 'excludes'. I've yet to stumble on to the right path.

Does anyone have any clue how to construct a spec for Getopt::Declare that works as I would like it?

Replies are listed 'Best First'.
Re: Getopt::Declare and bare arguments
by paulbort (Hermit) on Jul 01, 2004 at 20:55 UTC
    I don't know if it will help or not, but with GetOpt::EvaP, the parameters that aren't options are left in @ARGV, so $@ARGV should tell you which way to try to parse them. I don't know GetOpts::Declare at all, so I dont' know if GetOpt::EvaP is missing something critical. But it worked for me.

    --
    Spring: Forces, Coiled Again!
Re: Getopt::Declare and bare arguments
by Anonymous Monk on Jul 02, 2004 at 19:55 UTC
    You declare <machine> but <machinename> is mutex with <switchname>.