File Coverage

blib/lib/Crane/Options.pm
Criterion Covered Total %
statement 47 56 83.9
branch 19 28 67.8
condition 12 19 63.1
subroutine 6 6 100.0
pod 1 1 100.0
total 85 110 77.2


line stmt bran cond sub pod time code
1             # -*- coding: utf-8 -*-
2              
3              
4             package Crane::Options;
5              
6              
7 3     3   956 use Crane::Base qw( Exporter );
  3         83  
  3         23  
8              
9 3     3   23 use File::Basename qw( basename );
  3         7  
  3         474  
10 3     3   4903 use Getopt::Long qw( GetOptionsFromArray :config posix_default );
  3         49596  
  3         22  
11              
12              
13             our @EXPORT = qw(
14             &options
15             &args
16             );
17              
18             our @EXPORT_OPTS = qw(
19             $OPT_SEPARATOR
20            
21             $OPT_VERSION
22             $OPT_HELP
23             );
24              
25             our @EXPORT_OK = (
26             qw(
27             &load_options
28             ),
29            
30             @EXPORT_OPTS,
31             );
32              
33             our %EXPORT_TAGS = (
34             'opts' => \@EXPORT_OPTS,
35             );
36              
37              
38             Readonly::Scalar(our $OPT_SEPARATOR => []);
39             Readonly::Scalar(our $OPT_VERSION => [ 'version!', 'Shows version information and exits.' ]);
40             Readonly::Scalar(our $OPT_HELP => [ 'help!', 'Shows this help and exits.' ]);
41              
42              
43             sub options {
44            
45 17     17   2734 return state $options = do {
46 2 100       14 load_options(scalar @_ ? @_ : ( $OPT_VERSION, $OPT_HELP ));
47             };
48            
49             }
50              
51              
52             sub args {
53            
54 1     1   9 return state $args = [ @ARGV ];
55            
56             }
57              
58              
59             sub load_options {
60            
61 5     5 1 6003 my @options = grep { ref $_ eq 'ARRAY' } @_;
  28         64  
62 5         11 my $options = {};
63            
64             {
65 5         18 local $WARNING = 0;
  5         23  
66            
67             # Parse command line
68 5         15 GetOptionsFromArray(\@ARGV, $options, grep { defined } map { $_->[0] } @options);
  28         75  
  28         183  
69             }
70            
71             # Application file name
72 5         3008 my $app = basename($PROGRAM_NAME);
73            
74             # Show version information and exit
75 5 50       26 if ( $options->{'version'} ) {
76 0   0     0 my $version = $main::VERSION // 'not specified';
77            
78 0 0       0 print { *STDOUT } "$app version is $version\n" or confess($OS_ERROR);
  0         0  
79            
80 0         0 exit 0;
81             }
82            
83             # Create help ...
84 5         15 my $help = "$app \n\n";
85            
86 5 50       866 if ( scalar @options ) {
87 5         14 $help .= "OPTIONS:\n";
88             }
89            
90             # ... and check options
91 5         11 foreach my $opt ( @options ) {
92 28 50       67 if ( ref $opt ne 'ARRAY' ) {
93 0         0 next;
94             }
95            
96 28         97 my $spec = $opt->[0];
97 28         85 my $desc = $opt->[1];
98 28         77 my $params = $opt->[2];
99            
100             # Separator
101 28 100 33     233 if ( not defined $spec and not defined $desc and not defined $params ) {
    50 33        
102 5         9 $help .= "\n";
103             # Option
104             } elsif ( defined $spec and $spec =~ m{^([^!+=:]+)}si ) {
105 23         67 my @names = split m{[|]}si, $1;
106 23         31 my $name = $names[0];
107 23         34 my $short = ( grep { length == 1 } @names )[0];
  31         63  
108 23         28 my $long = ( grep { length >= 2 } @names )[0];
  31         55  
109            
110             # Check params
111 23 100       52 if ( ref $params eq 'HASH' ) {
112             # Default value
113 6 100 100     34 if ( exists $params->{'default'} and not exists $options->{ $name } ) {
114 3         9 $options->{ $name } = $params->{'default'};
115             }
116            
117             # Is required
118 6 100 66     28 if ( $params->{'required'} and not $options->{'help'} and not exists $options->{ $name } ) {
      100        
119 1         8 die "Option required: $name\n";
120             }
121             }
122            
123             # Add to help
124 22 100 100     141 $help .= sprintf q{ %-2s %-20s %s},
    100          
125             defined $short ? "-$short" : '',
126             defined $long ? "--$long" : '',
127            
128             $desc // '';
129            
130 22         53 $help .= "\n";
131             } else {
132 0         0 confess("Invalid option specification: $spec");
133             }
134             }
135            
136             # Show help and exit
137 4 50       18 if ( $options->{'help'} ) {
138 0 0       0 print { *STDOUT } $help or confess($OS_ERROR);
  0         0  
139            
140 0         0 exit 0;
141             }
142            
143 4         22 return $options;
144            
145             }
146              
147              
148             1;
149              
150              
151             =head1 NAME
152              
153             Crane::Options - Command line options and arguments parser
154              
155              
156             =head1 SYNOPSIS
157              
158             use Crane::Options;
159            
160             my $option = options->{'version'};
161             my $arg2 = args->[1];
162              
163              
164             =head1 DESCRIPTION
165              
166             Parses command line options and arguments. Options are available as hash
167             reference returned by L function and arguments are available as array
168             reference returned by L function.
169              
170             You can configure options by passing list of array references when first call
171             L function (see description below).
172              
173             By default two options are available: B and B.
174              
175              
176             =head1 EXPORTED CONSTANTS
177              
178             =head2 Tag :opts - predefined options
179              
180             =over
181              
182             =item B<$OPT_SEPARATOR>
183              
184             Not an option exaclty, just a separator in help output.
185              
186             Equals to:
187              
188             []
189              
190             =item B<$OPT_VERSION>
191              
192             Version information output.
193              
194             Equals to:
195              
196             [ 'version!', 'Shows version information and exits.' ]
197              
198             =item B<$OPT_HELP>
199              
200             Help output.
201              
202             Equals to:
203              
204             [ 'help!', Shows this help and exits.' ]
205              
206             =back
207              
208              
209             =head1 EXPORTED FUNCTIONS
210              
211             =over
212              
213             =item B (I<@options>)
214              
215             Returns hash reference to the command line options.
216              
217             Can be configured when first called with the list of I<@options>. To create an
218             option you should pass a list of array references with one required and two
219             mandatory items:
220              
221             =over
222              
223             =item B
224              
225             Scalar, required. Specification from L module.
226              
227             =item B
228              
229             Scalar. Text description (what is this option does?).
230              
231             =item B
232              
233             Hash reference. Additional parameters:
234              
235             =over
236              
237             =item B
238              
239             Default value for option if option does not exist.
240              
241             =item B
242              
243             Flag that option should be exists.
244              
245             =back
246              
247             =back
248              
249             Separator is empty array reference.
250              
251             =item B ()
252              
253             Returns array reference to command line arguments.
254              
255             =back
256              
257              
258             =head1 FUNCTIONS
259              
260             =over
261              
262             =item B (I<@options>)
263              
264             Parses command line arguments list I<@ARGV> and return reference to hash.
265              
266             See L<@options parameter description|/"options (@options)">.
267              
268             =back
269              
270              
271             =head1 ERRORS
272              
273             =over
274              
275             =item Invalid option specification: I<%s>
276              
277             Where I<%s> is specification string.
278              
279             Fires when required parameter of specification is not defined or incorrect.
280              
281             =back
282              
283              
284             =head1 DIAGNOSTICS
285              
286             =over
287              
288             =item Option required: I<%s>
289              
290             Where I<%s> is an option name.
291              
292             Option does not exist but required.
293              
294             =back
295              
296              
297             =head1 EXAMPLES
298              
299              
300             =head2 Simple option in compare with defaults
301              
302             Configuration:
303              
304             options(
305             [ 'config|C=s', 'Path to configuration file.' ],
306             $OPT_SEPARATOR,
307             $OPT_VERSION,
308             $OPT_HELP,
309             );
310              
311             Help output:
312              
313             example.pl
314             -C --config Path to configuration file.
315            
316             --version Shows version information and exists.
317             -? --help Shows this help and exits.
318              
319              
320             =head2 Two required arguments, one with default value and default options
321              
322             Configuration:
323              
324             options(
325             [ 'daemon|M!', 'Run as daemon.', { 'default' => 1 } ],
326             $OPT_SEPARATOR,
327             [ 'from=s', 'Start of the interval.', { 'required' => 1 } ],
328             [ 'to=s', 'End of the interval.', { 'required' => 1 } ],
329             $OPT_SEPARATOR,
330             $OPT_VERSION,
331             $OPT_HELP,
332             );
333              
334             Help output:
335              
336             example.pl
337             -M --daemon Run as daemon.
338            
339             --from Start of the interval.
340             --to End of the interval.
341            
342             --version Shows version information and exists.
343             -? --help Shows this help and exits.
344              
345              
346             =head1 BUGS
347              
348             Please report any bugs or feature requests to
349             L or to
350             L.
351              
352              
353             =head1 AUTHOR
354              
355             Tema Novikov,
356              
357              
358             =head1 COPYRIGHT AND LICENSE
359              
360             Copyright (C) 2013-2014 Tema Novikov.
361              
362             This library is free software; you can redistribute it and/or modify it under
363             the terms of the Artistic License 2.0. For details, see the full text of the
364             license in the file LICENSE.
365              
366              
367             =head1 SEE ALSO
368              
369             =over
370              
371             =item * B
372              
373             L
374              
375             =item * B
376              
377             L
378              
379             =back