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

Looking for some ideas concerning the following problem:

I want to write a script which takes some commandline options in the way git or cvs do:

scriptname GLOBAL_OPTIONS subcommand SUBCOMMAND_OPTIONS (for example cvs -d :sspi:cvs:/dir update -P)

The subcommand options might differ from subcommand to subcommand.

What's the best way to do this? Is there a perl package already?

Thanks in advance

Replies are listed 'Best First'.
Re: Parsing commandline with subcommands
by Loops (Curate) on Jul 18, 2013 at 09:32 UTC
    OptArgs and CLI::Framework both have support for sub-commands. Haven't used either of them myself though.
Re: Parsing commandline with subcommands
by Utilitarian (Vicar) on Jul 18, 2013 at 09:26 UTC
    you could use Getopt::Long and reformulate your commandline with scriptname -global -options -c "subcommand_1 -opt1 -opt2..-optn"

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: Parsing commandline with subcommands
by Anonymous Monk on Jul 18, 2013 at 09:42 UTC
Re: Parsing commandline with subcommands
by tobyink (Canon) on Jul 18, 2013 at 21:46 UTC
Re: Parsing commandline with subcommands
by eserte (Deacon) on Sep 18, 2015 at 15:17 UTC
    Getopt::Long's argument callback feature ("<>") may help here. The idea is to call GetOptions twice: first time with the global options, and to stop on the first unrecognized non-option. This one may be an invalid global option, or a subcmd, either valid or invalid. After this, call GetOptions again with the remaining arguments which would all be subcmd options.
    #!/usr/bin/perl use strict; use Getopt::Long; my $subcmd; my $global_option; my $subcmd_option; GetOptions("global" => \$global_option, "<>" => sub { my($arg) = @_; if ($arg =~ m{^-}) { die "usage error: unhandled option $arg detected in + global option section"; } elsif ($arg !~ m{^(subcmd1|subcmd2)$}) { die "usage error: invalid subcommand $arg"; } else { $subcmd = $arg; die "!FINISH"; } }) or die "usage error (in global option section)"; GetOptions("subcmd" => \$subcmd_option) or die "usage error (in subcmd option section)"; print <<EOF; global_option: $global_option subcmd: $subcmd subcmd_option: $subcmd_option leftover: @ARGV EOF __END__
Re: Parsing commandline with subcommands
by hoppfrosch (Scribe) on Jul 18, 2013 at 10:01 UTC
Re: Parsing commandline with subcommands
by vsespb (Chaplain) on Jul 18, 2013 at 12:12 UTC

    1. pass all possible options for command and subcommands to Getopt::Long (passing all ever possible options is also necessary for consistency as options are auto-abbreviated)

    2. After Getopt::Long processing @ARGV will contain non-options. Extract commands and subcommands from it

    3. Analyze your options like

    if delete $opts{myoption} ...

    4. After analyze if you still have something unrecognized in @ARGV or %opts - that is unused options an you need to throw an error

Re: Parsing commandline with subcommands
by code-ninja (Scribe) on Jul 18, 2013 at 09:11 UTC
    Not necessarily a good reply this might be but in one of my projects in C, I used the ReadLine Library to make a shell prompt. I guess Perl too has a port of the ReadLine library. Or maybe (again like C), you can use the getopt() function. Perl Doc has examples