From 38354ee9f02baa40f46e2689634077deeaf400ef Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 13 Jul 2018 11:58:33 +0100 Subject: more skeleton --- notes.pl | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 notes.pl (limited to 'notes.pl') diff --git a/notes.pl b/notes.pl new file mode 100644 index 0000000..d6bff3f --- /dev/null +++ b/notes.pl @@ -0,0 +1,88 @@ +#!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 -- cgit v1.2.3