line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CXC::Form::Tiny::Plugin::OptArgs2::Meta; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# ABSTRACT: Form metaclass role for OptArgs2 |
4
|
|
|
|
|
|
|
|
5
|
5
|
|
|
5
|
|
5306
|
use v5.20; |
|
5
|
|
|
|
|
21
|
|
6
|
|
|
|
|
|
|
|
7
|
5
|
|
|
5
|
|
31
|
use warnings; |
|
5
|
|
|
|
|
20
|
|
|
5
|
|
|
|
|
230
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '0.09'; |
10
|
|
|
|
|
|
|
|
11
|
5
|
|
|
5
|
|
2593
|
use Clone (); |
|
5
|
|
|
|
|
12472
|
|
|
5
|
|
|
|
|
175
|
|
12
|
5
|
|
|
5
|
|
45
|
use Scalar::Util qw( blessed ); |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
367
|
|
13
|
5
|
|
|
5
|
|
1635
|
use Ref::Util qw( is_plain_hashref is_arrayref is_regexpref is_ref ); |
|
5
|
|
|
|
|
1915
|
|
|
5
|
|
|
|
|
371
|
|
14
|
5
|
|
|
5
|
|
35
|
use Form::Tiny::Utils 'get_package_form_meta'; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
386
|
|
15
|
5
|
|
|
5
|
|
38
|
use Types::Standard qw( ArrayRef Bool CodeRef Dict Enum Int Optional RegexpRef Tuple Undef Value ); |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
81
|
|
16
|
5
|
|
|
5
|
|
22867
|
use Type::Params qw( signature_for ); |
|
5
|
|
|
|
|
21519
|
|
|
5
|
|
|
|
|
57
|
|
17
|
5
|
|
|
5
|
|
1756
|
use Types::Common::String qw ( NonEmptySimpleStr NonEmptyStr ); |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
55
|
|
18
|
|
|
|
|
|
|
|
19
|
5
|
|
|
5
|
|
5806
|
use Moo::Role; |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
62
|
|
20
|
|
|
|
|
|
|
|
21
|
5
|
|
|
5
|
|
2467
|
use experimental 'signatures', 'postderef', 'lexical_subs'; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
49
|
|
22
|
|
|
|
|
|
|
|
23
|
5
|
|
|
5
|
|
3701
|
use namespace::clean; |
|
5
|
|
|
|
|
60089
|
|
|
5
|
|
|
|
|
49
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my sub croak { |
26
|
0
|
|
|
0
|
|
0
|
require Carp; |
27
|
0
|
|
|
|
|
0
|
goto \&Carp::croak; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# need to stash which form this field was added to in order to handle |
31
|
|
|
|
|
|
|
# inheritance of inherited fields which aren't options, but which |
32
|
|
|
|
|
|
|
# contain nested forms which *are* options. |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
around add_field => sub ( $orig, $self, @parameters ) { |
35
|
|
|
|
|
|
|
# this may return either a FieldDefinition or a FieldDefinition, but |
36
|
|
|
|
|
|
|
# in either case, it has an addons methods. |
37
|
|
|
|
|
|
|
my $field = $self->$orig( @parameters ); |
38
|
|
|
|
|
|
|
$field->addons->{ +__PACKAGE__ }{package} = $self->package; |
39
|
|
|
|
|
|
|
return $field; |
40
|
|
|
|
|
|
|
}; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
has inherit_required => ( |
50
|
|
|
|
|
|
|
is => 'rwp', |
51
|
|
|
|
|
|
|
isa => Bool, |
52
|
13
|
|
|
13
|
|
543
|
builder => sub { !!1 }, |
53
|
|
|
|
|
|
|
); |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
has inherit_optargs => ( |
62
|
|
|
|
|
|
|
is => 'rwp', |
63
|
|
|
|
|
|
|
isa => Bool, |
64
|
13
|
|
|
13
|
|
59436
|
builder => sub { !!0 }, |
65
|
|
|
|
|
|
|
); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
has inherit_optargs_match => ( |
76
|
|
|
|
|
|
|
is => 'rwp', |
77
|
|
|
|
|
|
|
isa => Undef | ArrayRef [ Tuple [ Bool, RegexpRef ] ], |
78
|
15
|
|
|
15
|
|
13232
|
builder => sub { undef }, |
79
|
|
|
|
|
|
|
); |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
10
|
|
|
|
|
19
|
has _optargs => ( |
94
|
|
|
|
|
|
|
is => 'rwp', |
95
|
|
|
|
|
|
|
lazy => 1, |
96
|
|
|
|
|
|
|
init_arg => undef, |
97
|
|
|
|
|
|
|
## no critic (Subroutines::ProtectPrivateSubs ) |
98
|
10
|
|
|
10
|
|
151
|
builder => sub ( $self ) { $self->_build_opt_args->_optargs }, |
|
10
|
|
|
|
|
32
|
|
|
10
|
|
|
|
|
38
|
|
99
|
|
|
|
|
|
|
); |
100
|
|
|
|
|
|
|
|
101
|
10
|
|
|
10
|
1
|
172
|
sub optargs ( $self ) { |
|
10
|
|
|
|
|
31
|
|
|
10
|
|
|
|
|
36
|
|
102
|
10
|
|
|
|
|
253
|
return Clone::clone( $self->_optargs ); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
0
|
has rename => ( |
106
|
|
|
|
|
|
|
is => 'rwp', |
107
|
|
|
|
|
|
|
lazy => 1, |
108
|
|
|
|
|
|
|
init_arg => undef, |
109
|
0
|
|
|
0
|
|
0
|
builder => sub ( $self ) { $self->_build_opt_args->rename }, |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
110
|
|
|
|
|
|
|
); |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
|
121
|
2
|
|
|
2
|
1
|
6
|
sub rename_options ( $self, $opt ) { |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
122
|
2
|
|
|
|
|
57
|
my $rename = $self->rename; |
123
|
2
|
|
|
|
|
35
|
for my $from ( keys $opt->%* ) { |
124
|
19
|
|
|
|
|
39
|
my $to = $rename->{$from}; |
125
|
19
|
50
|
|
|
|
38
|
croak( "unexpected option key: $from\n" ) |
126
|
|
|
|
|
|
|
if !defined $to; |
127
|
19
|
|
|
|
|
53
|
$opt->{$to} = delete $opt->{$from}; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
148
|
2
|
|
|
2
|
1
|
64
|
sub inflate_optargs ( $self, $optargs ) { |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
149
|
|
|
|
|
|
|
|
150
|
2
|
|
|
|
|
5
|
state $folder = do { |
151
|
2
|
|
|
|
|
17
|
require Hash::Fold; |
152
|
2
|
|
|
|
|
18
|
Hash::Fold->new( delimiter => chr( 0 ) ); |
153
|
|
|
|
|
|
|
}; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# make a copy of the flattened hash |
156
|
2
|
|
|
|
|
7017
|
my %flat = $optargs->%*; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# translate the OptArgs names into that required by the Form::Tiny structure |
159
|
2
|
|
|
|
|
28
|
$self->rename_options( \%flat ); |
160
|
|
|
|
|
|
|
|
161
|
2
|
|
|
|
|
22
|
return $folder->unfold( \%flat ); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
165
|
10
|
|
|
10
|
|
44
|
sub _build_opt_args ( $self ) { |
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
19
|
|
166
|
10
|
|
|
|
|
20
|
my %rename; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
my @optargs; |
169
|
10
|
|
|
|
|
42
|
for my $aref ( $self->_create_options( \%rename )->@* ) { |
170
|
50
|
|
|
|
|
105
|
my ( $name, $spec ) = $aref->@*; |
171
|
50
|
|
|
|
|
207
|
my %spec = $spec->%*; |
172
|
50
|
|
|
|
|
95
|
delete $spec{order}; |
173
|
50
|
|
|
|
|
129
|
push @optargs, $name, \%spec; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
10
|
|
|
|
|
86
|
$self->_set__optargs( \@optargs ); |
177
|
10
|
|
|
|
|
58
|
$self->_set_rename( \%rename ); |
178
|
10
|
|
|
|
|
236
|
return $self; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
18
|
|
|
18
|
|
26
|
my sub _match_inherit_optargs ( $matches, $package ) { |
|
18
|
|
|
|
|
34
|
|
|
18
|
|
|
|
|
22
|
|
|
18
|
|
|
|
|
31
|
|
182
|
|
|
|
|
|
|
|
183
|
18
|
|
|
|
|
25
|
my $excluded = 0; |
184
|
|
|
|
|
|
|
|
185
|
18
|
|
|
|
|
36
|
for my $match ( $matches->@* ) { |
186
|
26
|
|
|
|
|
58
|
my ( $retval, $qr ) = $match->@*; |
187
|
26
|
100
|
|
|
|
141
|
return $retval if $package =~ $qr; |
188
|
16
|
100
|
|
|
|
42
|
$excluded++ unless $retval; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# if no exclusions, then user forgot to add the exclude all |
192
|
|
|
|
|
|
|
# catch-all at the end. just having inclusions doesn't make |
193
|
|
|
|
|
|
|
# sense. |
194
|
|
|
|
|
|
|
|
195
|
8
|
|
|
|
|
34
|
return $excluded != 0; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
87
|
|
|
87
|
|
129
|
sub _inherit_optargs ( $self, $package ) { |
|
87
|
|
|
|
|
134
|
|
|
87
|
|
|
|
|
134
|
|
|
87
|
|
|
|
|
125
|
|
199
|
|
|
|
|
|
|
|
200
|
87
|
|
66
|
|
|
671
|
return $package eq $self->package |
201
|
|
|
|
|
|
|
|| ( |
202
|
|
|
|
|
|
|
$self->inherit_optargs |
203
|
|
|
|
|
|
|
&& ( !defined $self->inherit_optargs_match |
204
|
|
|
|
|
|
|
|| _match_inherit_optargs( $self->inherit_optargs_match, $package ) ) ); |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# this has too many arguments |
208
|
|
|
|
|
|
|
sub _create_options ( |
209
|
27
|
|
|
|
|
41
|
$self, $rename, |
|
27
|
|
|
|
|
62
|
|
210
|
27
|
|
|
|
|
48
|
$path = [], |
211
|
27
|
|
|
|
|
60
|
$opt_path = [], |
212
|
27
|
|
|
|
|
160
|
$blueprint = $self->blueprint( recurse => 0 ), |
213
|
27
|
|
|
27
|
|
165
|
) |
|
27
|
|
|
|
|
13021
|
|
214
|
|
|
|
|
|
|
{ |
215
|
27
|
|
|
|
|
61
|
my @optargs; |
216
|
|
|
|
|
|
|
|
217
|
27
|
|
|
|
|
144
|
for my $field ( sort keys $blueprint->%* ) { |
218
|
|
|
|
|
|
|
|
219
|
91
|
|
|
|
|
196
|
my $def = $blueprint->{$field}; |
220
|
|
|
|
|
|
|
|
221
|
91
|
100
|
100
|
|
|
1743
|
if ( is_plain_hashref( $def ) || ( my $is_subform = $def->is_subform ) ) { |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# Normally a sub-form's options get a prefix based on the field name, e.g. |
224
|
|
|
|
|
|
|
# db.opts => --db-opts. Sometimes the extra levels are overkill for the option names, |
225
|
|
|
|
|
|
|
# so if the options entry contains 'name' specification, use that for the prefix. |
226
|
|
|
|
|
|
|
# unfortunately if the field name is nested, we only get here at the bottom of the |
227
|
|
|
|
|
|
|
# hierarchy, so need to backtrack. |
228
|
|
|
|
|
|
|
|
229
|
23
|
|
|
|
|
220
|
my @paths = ( [ $path->@*, $field ], [ $opt_path->@*, $field ] ); |
230
|
|
|
|
|
|
|
|
231
|
23
|
100
|
|
|
|
53
|
if ( $is_subform ) { |
232
|
|
|
|
|
|
|
|
233
|
19
|
|
33
|
|
|
72
|
my $addons = $def->addons->{ +__PACKAGE__ } // croak( 'no addons for field ' . $def->name ); |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# bail if we're not inheriting |
236
|
19
|
100
|
|
|
|
85
|
next unless $self->_inherit_optargs( $addons->{package} ); |
237
|
|
|
|
|
|
|
|
238
|
13
|
50
|
50
|
|
|
87
|
if ( defined( my $name = ( $addons->{optargs} // {} )->{name} ) ) { |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
## no critic (ControlStructures::ProhibitDeepNests) |
241
|
0
|
0
|
|
|
|
0
|
if ( my @fixup = $opt_path->@* ) { |
242
|
0
|
|
|
|
|
0
|
my @comp = split( /[.]/, $def->name ); |
243
|
0
|
|
|
|
|
0
|
splice( @fixup, @fixup - @comp, @comp, $name ); |
244
|
|
|
|
|
|
|
# replace default opt_path |
245
|
0
|
|
|
|
|
0
|
$paths[-1] = \@fixup; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
else { |
248
|
0
|
|
|
|
|
0
|
$paths[-1] = [$name]; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
13
|
|
|
|
|
84
|
push @optargs, get_package_form_meta( blessed $def->type )->_create_options( $rename, @paths )->@*; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
else { |
256
|
4
|
|
|
|
|
43
|
push @optargs, $self->_create_options( $rename, @paths, $def )->@*; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
else { |
261
|
68
|
|
33
|
|
|
748
|
my $addons = $def->addons->{ +__PACKAGE__ } // croak( 'no addons for field ' . $def->name ); |
262
|
68
|
50
|
|
|
|
170
|
next unless defined( my $orig_optargs = $addons->{optargs} ); |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
croak( "optargs initialized, but no option or argument specification for field $field?" ) |
265
|
68
|
50
|
|
|
|
164
|
if !defined $orig_optargs->{spec}; |
266
|
|
|
|
|
|
|
|
267
|
68
|
|
|
|
|
107
|
my $optargs = $orig_optargs->{spec}; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# This bit deals with creating the option name and then mapping it back onto the |
270
|
|
|
|
|
|
|
# Form::Tiny blueprint for the form, which may introduce extra layers in the |
271
|
|
|
|
|
|
|
# nested hash if the field name has multiple components. |
272
|
|
|
|
|
|
|
# Special cases arise: |
273
|
|
|
|
|
|
|
# 1) multi-component field name, e.g. 'output.parsed' |
274
|
|
|
|
|
|
|
# 2) options name ne field name, e.g. '--raw-output' ne 'output.raw'. |
275
|
|
|
|
|
|
|
# 3) field name has an underscore, which can get confused |
276
|
|
|
|
|
|
|
# when the options are unflattened, as underscore is |
277
|
|
|
|
|
|
|
# used to indicated nested structures |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# if @path > 1, then a multi-component name was given to form_field. |
281
|
|
|
|
|
|
|
# Form::Tiny doesn't keep track of sub-forms' parents, so it doesn't know |
282
|
|
|
|
|
|
|
# so we keep track of the entire path via $path. |
283
|
|
|
|
|
|
|
# we only need the last component to get the (leaf) form field name. |
284
|
68
|
|
|
|
|
1163
|
my $field_name = $def->get_name_path->path->[-1]; |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
# this is the fully qualified normalized field name, with |
287
|
|
|
|
|
|
|
# components separated by NUL and will be used create the |
288
|
|
|
|
|
|
|
# correct hierarchy when the options hash is unflattened. |
289
|
68
|
|
|
|
|
612
|
my $fq_field_name = join( chr( 0 ), $path->@*, $field_name ); |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# generate the fully qualified option name using the |
292
|
|
|
|
|
|
|
# specified field name. the field may specify an |
293
|
|
|
|
|
|
|
# alternate option name, so use that if specified. |
294
|
68
|
|
66
|
|
|
297
|
my $fq_option_name = $optargs->{name} // join( '_', $opt_path->@*, $field_name ); |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# store the mapping between option name and fully |
297
|
|
|
|
|
|
|
# qualified normalized field name. |
298
|
|
|
|
|
|
|
|
299
|
68
|
50
|
|
|
|
217
|
if ( defined( my $old_rename = $rename->{$fq_option_name} ) ) { |
300
|
0
|
|
|
|
|
0
|
croak( "redefined rename of $fq_option_name to $fq_field_name (originally to $old_rename)" ); |
301
|
|
|
|
|
|
|
} |
302
|
68
|
|
|
|
|
167
|
$rename->{$fq_option_name} = $fq_field_name; |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
$optargs->{default} = $def->default->() |
305
|
68
|
100
|
66
|
|
|
207
|
if $optargs->{show_default} && $def->has_default; |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
push @optargs, [ $fq_option_name, $optargs ] |
308
|
68
|
100
|
|
|
|
207
|
if $self->_inherit_optargs( $addons->{package} ); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
## no critic (BuiltinFunctions::RequireSimpleSortBlock) |
313
|
|
|
|
|
|
|
return [ |
314
|
|
|
|
|
|
|
# no order, pass 'em through |
315
|
72
|
|
|
|
|
182
|
( grep { !defined $_->[1]{order} } @optargs ), |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# order, sort 'em, but complain if multiple arguments with the |
318
|
|
|
|
|
|
|
# same order, as that is not deterministic |
319
|
|
|
|
|
|
|
( |
320
|
|
|
|
|
|
|
sort { |
321
|
2
|
|
|
|
|
7
|
my $order = $a->[1]{order} <=> $b->[1]{order}; |
322
|
2
|
50
|
|
|
|
10
|
croak( "$a->[0] and $b->[0] have the same argument order" ) |
323
|
|
|
|
|
|
|
if $order == 0; |
324
|
|
|
|
|
|
|
$order; |
325
|
|
|
|
|
|
|
} |
326
|
27
|
|
|
|
|
79
|
grep { defined $_->[1]{order} } @optargs |
|
72
|
|
|
|
|
225
|
|
327
|
|
|
|
|
|
|
) ]; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
33
|
|
|
33
|
|
61
|
sub _add_optarg ( $self, $field, $spec ) { |
|
33
|
|
|
|
|
60
|
|
|
33
|
|
|
|
|
55
|
|
|
33
|
|
|
|
|
56
|
|
|
33
|
|
|
|
|
49
|
|
331
|
33
|
|
50
|
|
|
135
|
my $stash = $field->addons->{ +__PACKAGE__ } //= {}; |
332
|
33
|
|
50
|
|
|
148
|
my $optargs = ( $stash->{optargs} //= {} ); |
333
|
|
|
|
|
|
|
croak( sprintf( 'duplicate definition for field %s', $field->name ) ) |
334
|
33
|
50
|
|
|
|
104
|
if defined $optargs->{spec}; |
335
|
|
|
|
|
|
|
|
336
|
33
|
100
|
66
|
|
|
232
|
$spec->{required} //= !!$field->required |
337
|
|
|
|
|
|
|
if $self->inherit_required; |
338
|
33
|
|
|
|
|
74
|
$optargs->{spec} = $spec; |
339
|
33
|
|
|
|
|
190
|
return; |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
5
|
|
|
5
|
|
12876
|
use constant OptionTypeEnums => qw( ArrayRef Flag Bool Counter HashRef Int Num Str ); |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
668
|
|
343
|
5
|
|
|
5
|
|
74
|
use constant OptionTypeMap => { map { $_ => "--$_" } OptionTypeEnums }; |
|
5
|
|
|
|
|
27
|
|
|
5
|
|
|
|
|
17
|
|
|
40
|
|
|
|
|
901
|
|
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
use constant OptionType => Enum( [ values OptionTypeMap->%* ] ) |
346
|
5
|
50
|
|
5
|
|
48
|
->plus_coercions( NonEmptySimpleStr, sub { /^--/ ? $_ : "--$_" } ); |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
49
|
|
|
17
|
|
|
|
|
55278
|
|
347
|
|
|
|
|
|
|
|
348
|
5
|
|
|
5
|
|
26587
|
use constant ArgumentTypeEnums => qw( ArrayRef HashRef Int Num Str SubCmd ); |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
405
|
|
349
|
5
|
|
|
5
|
|
36
|
use constant ArgumentType => Enum [ArgumentTypeEnums]; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
33
|
|
350
|
5
|
|
|
5
|
|
16868
|
use constant ArgumentTypeMap => { map { $_ => $_ } ArgumentTypeEnums() }; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
19
|
|
|
30
|
|
|
|
|
3347
|
|
351
|
|
|
|
|
|
|
|
352
|
14
|
|
|
14
|
|
26
|
sub _resolve_type ( $field, $type_set ) { |
|
14
|
|
|
|
|
22
|
|
|
14
|
|
|
|
|
23
|
|
|
14
|
|
|
|
|
22
|
|
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# dynamic fields don't have types |
355
|
|
|
|
|
|
|
return undef |
356
|
14
|
50
|
33
|
|
|
149
|
unless defined $field |
|
|
|
33
|
|
|
|
|
357
|
|
|
|
|
|
|
&& $field->isa( 'Form::Tiny::FieldDefinition' ) |
358
|
|
|
|
|
|
|
&& $field->has_type; |
359
|
|
|
|
|
|
|
|
360
|
14
|
|
|
|
|
35
|
my $type = $field->type; |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# take care of top level Any. Many other types inherit (eventually) from Any, |
363
|
|
|
|
|
|
|
# so the inheritance scan below will resolve types we don't support |
364
|
|
|
|
|
|
|
# if we add Any to OptionTypeMap and ArgumentTypeMap |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
return $type_set->{Str} |
367
|
14
|
100
|
|
|
|
53
|
if $type->name eq 'Any'; |
368
|
|
|
|
|
|
|
|
369
|
12
|
|
|
|
|
90
|
while ( defined $type ) { |
370
|
21
|
100
|
|
|
|
84
|
return $type_set->{ $type->name } if exists $type_set->{ $type->name }; |
371
|
9
|
|
|
|
|
57
|
$type = $type->parent; |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
0
|
|
|
|
|
|
return undef; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
signature_for _dsl_add_option => ( |
378
|
|
|
|
|
|
|
method => 1, |
379
|
|
|
|
|
|
|
head => 1, # field context |
380
|
|
|
|
|
|
|
bless => !!0, |
381
|
|
|
|
|
|
|
named => [ |
382
|
|
|
|
|
|
|
name => Optional [NonEmptySimpleStr], |
383
|
|
|
|
|
|
|
alias => Optional [NonEmptySimpleStr], |
384
|
|
|
|
|
|
|
comment => NonEmptySimpleStr, |
385
|
|
|
|
|
|
|
default => Optional [ Value | CodeRef ], |
386
|
|
|
|
|
|
|
required => Optional [Bool], |
387
|
|
|
|
|
|
|
hidden => Optional [Bool], |
388
|
|
|
|
|
|
|
isa => Optional [OptionType], |
389
|
|
|
|
|
|
|
isa_name => Optional [NonEmptySimpleStr], |
390
|
|
|
|
|
|
|
show_default => Optional [Bool], |
391
|
|
|
|
|
|
|
trigger => Optional [CodeRef], |
392
|
|
|
|
|
|
|
], |
393
|
|
|
|
|
|
|
); |
394
|
|
|
|
|
|
|
sub _dsl_add_option ( $self, $context, $spec ) { |
395
|
|
|
|
|
|
|
croak( q{The 'option' directive must be used after a field definition} ) |
396
|
|
|
|
|
|
|
if !defined( $context ); |
397
|
|
|
|
|
|
|
my %spec = $spec->%*; |
398
|
|
|
|
|
|
|
$spec{isa} //= _resolve_type( $context, OptionTypeMap ) |
399
|
|
|
|
|
|
|
// croak( sprintf( q{'isa' attribute not specified or resolved for %s}, $context->name ) ); |
400
|
|
|
|
|
|
|
$self->_add_optarg( $context, \%spec ); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
signature_for _dsl_add_argument => ( |
404
|
|
|
|
|
|
|
method => 1, |
405
|
|
|
|
|
|
|
head => 1, |
406
|
|
|
|
|
|
|
bless => !!0, |
407
|
|
|
|
|
|
|
named => [ |
408
|
|
|
|
|
|
|
name => Optional [NonEmptySimpleStr], |
409
|
|
|
|
|
|
|
comment => NonEmptySimpleStr, |
410
|
|
|
|
|
|
|
default => Optional [ Value | CodeRef ], |
411
|
|
|
|
|
|
|
greedy => Optional [Bool], |
412
|
|
|
|
|
|
|
fallthru => Optional [Bool], |
413
|
|
|
|
|
|
|
isa => Optional [ArgumentType], |
414
|
|
|
|
|
|
|
isa_name => Optional [NonEmptySimpleStr], |
415
|
|
|
|
|
|
|
required => Optional [Bool], |
416
|
|
|
|
|
|
|
show_default => Optional [Bool], |
417
|
|
|
|
|
|
|
order => Int, |
418
|
|
|
|
|
|
|
], |
419
|
|
|
|
|
|
|
); |
420
|
|
|
|
|
|
|
sub _dsl_add_argument ( $self, $context, $spec ) { |
421
|
|
|
|
|
|
|
croak( q{The 'argument' directive must be used after a field definition} ) |
422
|
|
|
|
|
|
|
if !defined( $context ); |
423
|
|
|
|
|
|
|
my %spec = $spec->%*; |
424
|
|
|
|
|
|
|
$spec{isa} //= _resolve_type( $context, ArgumentTypeMap ) |
425
|
|
|
|
|
|
|
// croak( sprintf( q{'isa' attribute not specified or resolved for %s}, $context->name ) ); |
426
|
|
|
|
|
|
|
$self->_add_optarg( $context, \%spec ); |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
5
|
|
|
5
|
|
48
|
use constant { INCLUDE => q{+}, EXCLUDE => q{-} }; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
2894
|
|
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
my sub parse_inherit_matches ( $default, $entries ) { |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
my @matches; |
434
|
|
|
|
|
|
|
my $include = $default; |
435
|
|
|
|
|
|
|
for my $entry ( $entries->@* ) { |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
if ( is_arrayref( $entry ) ) { |
438
|
|
|
|
|
|
|
push @matches, __SUB__->( $include, $entry )->@*; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
elsif ( is_regexpref( $entry ) ) { |
442
|
|
|
|
|
|
|
push @matches, [ $include eq INCLUDE, $entry ]; |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
elsif ( $entry eq EXCLUDE || $entry eq EXCLUDE ) { |
446
|
|
|
|
|
|
|
$include = $entry; |
447
|
|
|
|
|
|
|
next; # avoid reset of $include to default below |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
# every thing else is a regexp as a string; turn into a regexp |
451
|
|
|
|
|
|
|
else { |
452
|
|
|
|
|
|
|
push @matches, [ $include eq INCLUDE, qr/$entry/ ]; |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
# reset include to default |
456
|
|
|
|
|
|
|
$include = $default; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
return \@matches; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
signature_for _dsl_optargs_opts => ( |
464
|
|
|
|
|
|
|
method => 1, |
465
|
|
|
|
|
|
|
head => 1, |
466
|
|
|
|
|
|
|
named => [ |
467
|
|
|
|
|
|
|
inherit_required => Optional [Bool], |
468
|
|
|
|
|
|
|
inherit_optargs => Optional [Bool], |
469
|
|
|
|
|
|
|
inherit_optargs_match => Optional [ArrayRef], |
470
|
|
|
|
|
|
|
], |
471
|
|
|
|
|
|
|
); |
472
|
|
|
|
|
|
|
sub _dsl_optargs_opts ( $self, $context, $args ) { |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
croak( q{The 'optargs_opts' directive must be used before any fields are defined} ) |
475
|
|
|
|
|
|
|
if defined( $context ); |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
$self->_set_inherit_required( $args->inherit_required ) |
478
|
|
|
|
|
|
|
if $args->has_inherit_required; |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
$self->_set_inherit_optargs( $args->inherit_optargs ) |
481
|
|
|
|
|
|
|
if $args->has_inherit_optargs; |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
if ( $args->has_inherit_optargs_match ) { |
484
|
|
|
|
|
|
|
my $match = $args->inherit_optargs_match; |
485
|
|
|
|
|
|
|
$match = [$match] unless is_arrayref( $match ); |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
my $matches = parse_inherit_matches( INCLUDE, $match ); |
488
|
|
|
|
|
|
|
$self->_set_inherit_optargs_match( $matches ); |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
# |
495
|
|
|
|
|
|
|
# This file is part of CXC-Form-Tiny-Plugin-OptArgs2 |
496
|
|
|
|
|
|
|
# |
497
|
|
|
|
|
|
|
# This software is Copyright (c) 2023 by Smithsonian Astrophysical Observatory. |
498
|
|
|
|
|
|
|
# |
499
|
|
|
|
|
|
|
# This is free software, licensed under: |
500
|
|
|
|
|
|
|
# |
501
|
|
|
|
|
|
|
# The GNU General Public License, Version 3, June 2007 |
502
|
|
|
|
|
|
|
# |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
1; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
__END__ |