File Coverage

blib/lib/Smart/Options/Declare.pm
Criterion Covered Total %
statement 58 60 96.6
branch 27 32 84.3
condition 3 5 60.0
subroutine 7 7 100.0
pod 2 2 100.0
total 97 106 91.5


line stmt bran cond sub pod time code
1             package Smart::Options::Declare;
2 11     11   8833 use strict;
  11         23  
  11         709  
3 11     11   59 use warnings;
  11         22  
  11         290  
4              
5 11     11   54 use Exporter 'import';
  11         18  
  11         397  
6 11     11   9311 use Smart::Options;
  11         37  
  11         1451  
7 11     11   15127 use PadWalker qw/var_name/;
  11         14856  
  11         15155  
8              
9             our @EXPORT = qw(opts opts_coerce);
10              
11             our $COERCE = {
12                 Multiple => {
13                     type => 'ArrayRef',
14                     generater => sub {
15                         if ( defined $_[0] ) {
16                             return [
17                                 split(
18                                     qr{,},
19                                     ref( $_[0] ) eq 'ARRAY' ? join( q{,}, @{ $_[0] } ) : $_[0]
20                                 )
21                             ];
22                         } else {
23                             return $_[0];
24                         }
25                     }
26                 }
27             };
28             my %is_invocant = map{ $_ => undef } qw($self $class);
29              
30             sub opts {
31                 {
32 28     28 1 18855         package DB;
33 28         264         () = caller(1);
34                 }
35              
36 28 100 50     329     if ( exists $is_invocant{ var_name( 1, \$_[0] ) || '' } ) {
37 6         13         $_[0] = shift @DB::args;
38 6         10         shift;
39                 }
40              
41 28         193     my $opt = Smart::Options->new();
42 28         113     $opt->type(config => 'Config');
43              
44 28         106     for ( my $i = 0 ; $i < @_ ; $i++ ) {
45 36 50       206         ( my $name = var_name( 1, \$_[$i] ) )
46                       or Carp::croak('usage: opts my $var => TYPE, ...');
47              
48 36         158         $name =~ s/^\$//;
49              
50 36 100       127         if ($name =~ /_/) {
51 5         16             (my $newname = $name) =~ s/_/-/g;
52 5         101             $opt->alias($newname => $name);
53              
54 5         9             $name = $newname;
55                     }
56              
57 36         78         my $rule = $_[$i+1];
58              
59 36 100       95         if ($rule) {
60 32 100 66     154             if (ref($rule) && ref($rule) eq 'HASH') {
61              
62 17 100       51                 if ($rule->{default}) {
63 2         8                     $opt->default($name => $rule->{default});
64                             }
65              
66 17 100       46                 if ($rule->{required}) {
67 3         95                     $opt->demand($name);
68                             }
69              
70 17 100       45                 if ($rule->{alias}) {
71 6         23                     $opt->alias($rule->{alias} => $name);
72                             }
73              
74 17 100       47                 if ($rule->{comment}) {
75 1         5                     $opt->describe($name => $rule->{comment});
76                             }
77              
78 17 50       51                 if (my $isa = $rule->{isa}) {
79 17 50       39                     if ($isa eq 'Bool') {
80 0         0                         $opt->boolean($name);
81                                 }
82 17         52                     $opt->type($name => $isa);
83                             }
84                         }
85                         else {
86 15 50       46                 if ($rule eq 'Bool') {
87 0         0                     $opt->boolean($name);
88                             }
89 15         51                 $opt->type($name => $rule);
90                         }
91                     }
92              
93             #auto set alias
94 36 100       175         if (length($name) > 1) {
95 17         74             $opt->alias(substr($name,0,1) => $name);
96                     }
97              
98 36 100       328         $i++ if defined $_[$i+1]; # discard type info
99                 }
100              
101 28         143     while (my ($isa, $c) = each(%$COERCE)) {
102 31         260         $opt->coerce($isa => $c->{type}, $c->{generater});
103                 }
104              
105 28         114     my $argv = $opt->parse;
106 24         94     for ( my $i = 0 ; $i < @_ ; $i++ ) {
107 29 50       155         ( my $name = var_name( 1, \$_[$i] ) )
108                       or Carp::croak('usage: opts my $var => TYPE, ...');
109              
110 29         117         $name =~ s/^\$//;
111              
112 29         68         $_[$i] = $argv->{$name};
113 29 100       411         $i++ if defined $_[$i+1]; # discard type info
114                 }
115             }
116              
117             sub opts_coerce {
118 1     1 1 12     my ($isa, $type, $generater) = @_;
119              
120 1         7     $COERCE->{$isa} = { type => $type, generater => $generater };
121             }
122              
123             1;
124             __END__
125            
126             =encoding utf8
127            
128             =head1 NAME
129            
130             Smart::Options::Declare - DSL for Smart::Options
131            
132             =head1 SYNOPSIS
133            
134             use Smart::Options::Declare;
135            
136             opts my $rif => 'Int', my $xup => 'Num';
137            
138             if ($rif - 5 * $xup > 7.138) {
139             say 'Buy more fiffiwobbles';
140             }
141             else {
142             say 'Sell the xupptumblers';
143             }
144            
145             # $ ./example.pl --rif=55 --xup=9.52
146             # Buy more fiffiwobbles
147             #
148             # $ ./example.pl --rif 12 --xup 8.1
149             # Sell the xupptumblers
150            
151             =head1 DESCRIPTION
152            
153             Smart::Options::Declare is a library which offers DSL for Smart::Options.
154            
155             =head1 METHOD
156            
157             =head2 opts $var => TYPE, $var2 => { isa => TYPE, RULE => ... }
158            
159             set option value to variable.
160            
161             use Smart::Options::Declare;
162            
163             opts my $var => 'Str', my $value => { isa => 'Int', default => 4 };
164            
165             =head2 opts_coerce ( NewType, Source, Generater )
166            
167             define new type and convert logic.
168            
169             opts_coerce Time => 'Str', sub { Time::Piece->strptime($_[0]) }
170            
171             opts my $time => 'Time';
172            
173             $time->hour;
174            
175             =head1 RULE
176            
177             =head2 isa
178             define option value type. see L</TYPES>.
179            
180             =head2 required
181             define option value is required.
182            
183             =head2 default
184             define options default value. If passed a coderef, it
185             will be executed if no value is provided on the command line.
186            
187             =head2 alias
188             define option param's alias.
189            
190             =head2 comment
191             this comment is used to generate help. help can show --help
192            
193             =head1 TYPES
194            
195             =head2 Str
196            
197             =head2 Int
198            
199             =head2 Num
200            
201             =head2 Bool
202            
203             =head2 ArrayRef
204            
205             =head2 HashRef
206            
207             =head2 Multiple
208            
209             This subtype is based off of ArrayRef. It will attempt to split any values passed on the command line on a comma: that is,
210            
211             opts my $foo => 'ArrayRef';
212             # script.pl --foo=one --foo=two,three
213             # => ['one', 'two,three']
214            
215             will become
216            
217             opts my $foo => 'Multiple';
218             # script.pl --foo=one --foo=two,three
219             # => ['one', 'two', 'three']
220            
221             =head1 AUTHOR
222            
223             Kan Fushihara E<lt>kan.fushihara@gmail.comE<gt>
224            
225             =head1 SEE ALSO
226            
227             L<opts>
228            
229             =head1 LICENSE
230            
231             Copyright (C) Kan Fushihara
232            
233             This library is free software; you can redistribute it and/or modify
234             it under the same terms as Perl itself.
235            
236             =cut
237