summaryrefslogtreecommitdiff
path: root/notes.txt
blob: d6bff3fdd613ec6e50c45df70fb3b3dc0ada7a11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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