#!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
