#!perl Getopt::Dakkar->new({ name => basename($0), title => from_pod('NAME'), synopsis => from_pod('SYNOPSIS'), class => $a_class_name, # object => $an_object, # at most one of these two is allowed # maybe object should be passed to the ->run method, not here? # but I like the idea of different options / parameters / # subcommands having their own objects op => $method, # optional options => [ { name => 'some-opt', alias => [qw(s O)], # equivalent to switches => [qw(some-opt s O)], type => Type::Tiny::something, # special cases for path, enum, bool # 'counter' would be useful # also, special cases for arrays and hashes required => 1, validate => \&foo, # defaults to the type::tiny assertion complete_shell => \&cs, # auto-generated for path, enum, more? complete => \&bar, # only if there's no complete_shell op => $method, # optional }, ... ], parameters => [ { # like options, but no aliases / switches }, ... ], # you can't have both parameters and subcommands subcommands => [ { # like top-level }, ... ], }); =head1 LOGIC - options and parameters can optionally be mixed (like other getopts) - short options can optionally be bundled normal parsing: at each level: - shift @ARGV, match against "-$short_option" or "--$long_option", eat argument if needed - if no match, and subcommands - match against subcommands - if no match, and we have a default/implied subcommands, assume that and recurse - error out - if no match, and parameters - match parameters positionally just before recursing (or at the end): - if we don't have a $state, init it with $object, or $class->new($argpack) ($class defaults to a hash-like thing that has a 'merge_with' method) - call $state->$op($argpack) ($op defaults to 'merge_with') - $argpack has a weakref to the Getopt::Dakkar object which means: - if no class/object/op is passed, at the end we have hash-like state with all the arguments/optios merged in - if we only have an op at the last step, it will be invoked with all the accumulated info - ops at different levels can do whatever they want shell completion: - the various complete_shell are put together into a big function - if there's a 'complete' (non-shell), the function will GETOPT_DAKKAR_COMPLETE=1 $name "$@" (the last word may be empty if we're TAB-ing after a IFS) - the program will parse normally - on validation error, warn, ignore the failed argument, and carry on - then invoke the completion function $state->$complete($argpack) - and return to the shell everything that was returned - check App::Spec trick to print more than what's completed