File Coverage

blib/lib/Getopt/App.pm
Criterion Covered Total %
statement 193 200 96.5
branch 84 100 84.0
condition 31 41 75.6
subroutine 27 27 100.0
pod 5 5 100.0
total 340 373 91.1


line stmt bran cond sub pod time code
1             package Getopt::App;
2 7     7   1600053 use feature qw(:5.16);
  7         50  
  7         1124  
3 7     7   56 use strict;
  7         13  
  7         139  
4 7     7   54 use warnings;
  7         14  
  7         212  
5 7     7   44 use utf8;
  7         18  
  7         46  
6              
7 7     7   237 use Carp qw(croak);
  7         11  
  7         323  
8 7     7   5831 use Getopt::Long ();
  7         74809  
  7         266  
9 7     7   57 use List::Util qw(first);
  7         21  
  7         10128  
10              
11             our $VERSION = '0.11';
12              
13             our ($OPT_COMMENT_RE, $OPTIONS, $SUBCOMMAND, $SUBCOMMANDS, %APPS) = (qr{\s+\#\s+});
14              
15             our $call_maybe = sub {
16             my ($app, $m) = (shift, shift);
17             local $Getopt::App::APP_CLASS;
18             $m = $app->can($m) || __PACKAGE__->can("_$m");
19             return $m ? $app->$m(@_) : undef;
20             };
21              
22             sub bundle {
23 1     1 1 7552 my ($class, $script, $OUT) = (@_, \*STDOUT);
24 1         4 my ($package, @script);
25              
26 1 50       50 open my $SCRIPT, '<', $script or croak "Can't read $script: $!";
27 1         41 while (my $line = readline $SCRIPT) {
28 2 100       18 if ($line =~ m!^\s*package\s+\S+\s*;!) { # look for app class name
    50          
29 1         15 $package .= $line;
30 1         4 last;
31             }
32             elsif ($. == 1) { # look for hashbang
33 1 50       8 $line =~ m/^#!/ ? print {$OUT} $line : do { print {$OUT} "#!$^X\n"; push @script, $line };
  1         7  
  0         0  
  0         0  
  0         0  
34             }
35             else {
36 0         0 push @script, $line;
37 0 0       0 last if $line =~ m!^[^#]+;!;
38             }
39             }
40              
41 1         8 my $out_line = '';
42 1 50       56 open my $SELF, '<', __FILE__ or croak "Can't read Getopt::App: $!";
43 1         70 while (my $line = readline $SELF) {
44 267 100       1504 next if $line =~ m!(?:\bVERSION\s|^\s*$)!; # TODO: Should version get skipped?
45 220 100       420 next if $line =~ m!^sub bundle\s\{! .. $line =~ m!^}$!; # skip bundle()
46 177 100       280 last if $line =~ m!^1;\s*$!; # do not include POD
47              
48 176         214 chomp $line;
49 176 100       331 if ($line =~ m!^sub\s!) {
    100          
50 15 100       35 print {$OUT} $out_line, "\n" if $out_line;
  1         5  
51 15 100       46 $line =~ m!\}$! ? print {$OUT} $line, "\n" : ($out_line = $line);
  2         9  
52             }
53             elsif ($line =~ m!^}$!) {
54 13         23 print {$OUT} $out_line, $line, "\n";
  13         30  
55 13         37 $out_line = '';
56             }
57             else {
58 148         385 $line =~ s!^[ ]{2,}!!; # remove leading white space
59 148         230 $line =~ s!\#\s.*!!; # remove comments
60 148         392 $out_line .= $line;
61             }
62             }
63              
64 1         12 print {$OUT} qq(BEGIN{\$INC{'Getopt/App.pm'}='BUNDLED'}\n);
  1         6  
65 1   50     3 print {$OUT} +($package || "package main\n");
  1         4  
66 1         4 print {$OUT} @script;
  1         14  
67 1         6 print {$OUT} $_ while readline $SCRIPT;
  2         39  
68             }
69              
70             sub capture {
71 22     22 1 47510 my ($app, $argv) = @_;
72 22         61 my ($exit_value, $stderr, $stdout) = (-1, '', '');
73              
74 22         56 local *STDERR;
75 22         42 local *STDOUT;
76 5     5   34 open STDERR, '>', \$stderr;
  5         10  
  5         37  
  22         359  
77 22         4460 open STDOUT, '>', \$stdout;
78 22         77 ($!, $@) = (0, '');
79             eval {
80 22   100     102 $exit_value = $app->($argv || [@ARGV]);
81 19         69 1;
82 22 100       44 } or do {
83 3         93 print STDERR $@;
84 3         51 $exit_value = int $!;
85             };
86              
87 22         173 return [$stdout, $stderr, $exit_value];
88             }
89              
90             sub extract_usage {
91 4     4 1 23 my %pod2usage;
92 4         11 $pod2usage{'-sections'} = shift;
93 4   33     27 $pod2usage{'-input'} = shift || (caller)[1];
94 4 100       16 $pod2usage{'-verbose'} = 99 if $pod2usage{'-sections'};
95              
96 4         1182 require Pod::Usage;
97 4         79023 open my $USAGE, '>', \my $usage;
98 4         40 Pod::Usage::pod2usage(-exitval => 'noexit', -output => $USAGE, %pod2usage);
99 4         13719 close $USAGE;
100              
101 4   100     20 $usage //= '';
102 4 100       21 $usage =~ s!^(.*?)\n!!s if $pod2usage{'-sections'};
103 4         27 $usage =~ s!^Usage:\n\s+([A-Z])!$1!s; # Remove "Usage" header if SYNOPSIS has a description
104 4         17 $usage =~ s!^ !!gm;
105              
106 4   100     30 return join '', $usage, _usage_for_subcommands($SUBCOMMANDS || []), _usage_for_options($OPTIONS || []);
      50        
107             }
108              
109             sub import {
110 20     20   18592 my ($class, @flags) = @_;
111 20         56 my $caller = caller;
112              
113 20         463 $_->import for qw(strict warnings utf8);
114 20         1519 feature->import(':5.16');
115              
116 20         47 my $skip_default;
117 7     7   88 no strict qw(refs);
  7         21  
  7         16836  
118 20         84 while (my $flag = shift @flags) {
119 10 100       97 if ($flag eq '-capture') {
    100          
    50          
    50          
120 6         14 *{"$caller\::capture"} = \&capture;
  6         37  
121 6         25 $skip_default = 1;
122             }
123             elsif ($flag eq '-complete') {
124 2         460 require Getopt::App::Complete;
125 2         8 *{"$caller\::generate_completion_script"} = \&Getopt::App::Complete::generate_completion_script;
  2         23  
126             }
127             elsif ($flag eq '-signatures') {
128 0         0 require experimental;
129 0         0 experimental->import(qw(signatures));
130             }
131             elsif ($flag !~ /^-/) {
132 2 100       207 croak "package definition required - cannot extend main with $flag!" if $caller eq 'main';
133 1 50       110 croak "require $flag FAIL $@" unless eval "require $flag;1";
134 1         9 push @{"${caller}::ISA"}, $flag;
  1         20  
135             }
136             }
137              
138 19 100       12000 unless ($skip_default) {
139 13 50       218 *{"$caller\::extract_usage"} = \&extract_usage unless $caller->can('extract_usage');
  13         65  
140 13 50       89 *{"$caller\::new"} = \&new unless $caller->can('new');
  13         43  
141 13         32 *{"$caller\::run"} = \&run;
  13         1468  
142             }
143             }
144              
145             sub new {
146 49     49 1 2246 my $class = shift;
147 49 100 33     276 bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class;
  1 100       8  
148             }
149              
150             sub run {
151 57     57 1 263 my @rules = @_;
152 57   66     182 my $class = $Getopt::App::APP_CLASS || caller;
153 45     45   6624 return sub { local $Getopt::App::APP_CLASS = $class; run(@_, @rules) }
  45         119  
154 57 100 66     290 if !$Getopt::App::APP_CLASS and defined wantarray;
155              
156 45         84 my $cb = pop @rules;
157 45 50       136 my $argv = ref $rules[0] eq 'ARRAY' ? shift @rules : [@ARGV];
158 45         107 local $OPTIONS = [@rules];
159 45         80 @rules = map {s!$OPT_COMMENT_RE.*$!!r} @rules;
  76         523  
160              
161 45         221 my $app = $class->new;
162 45 100 66     184 return $app->$call_maybe('getopt_complete_reply') if defined $ENV{COMP_POINT} and defined $ENV{COMP_LINE};
163              
164 35         105 $app->$call_maybe(getopt_pre_process_argv => $argv);
165              
166 35         119 local $SUBCOMMANDS = $app->$call_maybe('getopt_subcommands');
167 35 100       358 my $exit_value = $SUBCOMMANDS ? _subcommand_run_maybe($app, $SUBCOMMANDS, $argv) : undef;
168 31 100       82 return _exit($app, $exit_value) if defined $exit_value;
169              
170 24         51 my @configure = $app->$call_maybe('getopt_configure');
171 24         98 my $prev = Getopt::Long::Configure(@configure);
172 24 100       1792 my $valid = Getopt::Long::GetOptionsFromArray($argv, $app, @rules) ? 1 : 0;
173 24         5182 Getopt::Long::Configure($prev);
174 24         455 $app->$call_maybe(getopt_post_process_argv => $argv, {valid => $valid});
175              
176 22 100       252 return _exit($app, $valid ? $app->$cb(@$argv) : 1);
177             }
178              
179 10     10   35 sub _getopt_complete_reply { Getopt::App::Complete::complete_reply(@_) }
180              
181 22     22   76 sub _getopt_configure {qw(bundling no_auto_abbrev no_ignore_case pass_through require_order)}
182              
183             sub _getopt_load_subcommand {
184 6     6   41 my ($app, $subcommand, $argv) = @_;
185 6 50       30 return $subcommand->[1] if ref $subcommand->[1] eq 'CODE';
186              
187 6         34 ($@, $!) = ('', 0);
188 6 100       2872 croak "Unable to load subcommand $subcommand->[0]: $@ ($!)" unless my $code = do $subcommand->[1];
189 5         24 return $code;
190             }
191              
192             sub _getopt_post_process_argv {
193 21     21   49 my ($app, $argv, $state) = @_;
194 21 50       53 return unless $state->{valid};
195 21 100 100     87 return unless $argv->[0] and $argv->[0] =~ m!^-!;
196 1         3 $! = 1;
197 1         14 die "Invalid argument or argument order: @$argv\n";
198             }
199              
200             sub _getopt_unknown_subcommand {
201 1     1   4 my ($app, $argv) = @_;
202 1         3 $! = 2;
203 1         14 die "Unknown subcommand: $argv->[0]\n";
204             }
205              
206             sub _exit {
207 29     29   156 my ($app, $exit_value) = @_;
208 29   100     58 $exit_value = $app->$call_maybe(getopt_post_process_exit_value => $exit_value) // $exit_value;
209 29 100 100     175 $exit_value = 0 unless $exit_value and $exit_value =~ m!^\d{1,3}$!;
210 29 100       70 $exit_value = 255 unless $exit_value < 255;
211 29 50       61 exit $exit_value unless $Getopt::App::APP_CLASS;
212 29         274 return $exit_value;
213             }
214              
215             sub _subcommand_run {
216 11     11   25 my ($app, $subcommand, $argv) = @_;
217 11         40 local $Getopt::App::SUBCOMMAND = $subcommand;
218 11 100       38 unless ($APPS{$subcommand->[1]}) {
219 6         17 $APPS{$subcommand->[1]} = $app->$call_maybe(getopt_load_subcommand => $subcommand, $argv);
220 5 50       25 croak "$subcommand->[0] did not return a code ref" unless ref $APPS{$subcommand->[1]} eq 'CODE';
221             }
222              
223 10         49 return $APPS{$subcommand->[1]}->([@$argv[1 .. $#$argv]]);
224             }
225              
226             sub _subcommand_run_maybe {
227 15     15   37 my ($app, $subcommands, $argv) = @_;
228 15 100 100     93 return undef unless $argv->[0] and $argv->[0] =~ m!^\w!;
229             return $app->$call_maybe(getopt_unknown_subcommand => $argv)
230 12 100   35   90 unless my $subcommand = first { $_->[0] eq $argv->[0] } @$subcommands;
  35         79  
231 8         35 return _subcommand_run($app, $subcommand, $argv);
232             }
233              
234             sub _usage_for_options {
235 4     4   9 my ($rules) = @_;
236 4 100       31 return '' unless @$rules;
237              
238 3         13 my ($len, @options) = (0);
239 3         9 for (@$rules) {
240 8         51 my @o = split $OPT_COMMENT_RE, $_, 2;
241 8         29 $o[0] =~ s/(=[si][@%]?|\!|\+)$//;
242 8 100       28 $o[0] = join ', ', map { length($_) == 1 ? "-$_" : "--$_" } sort { length($b) <=> length($a) } split /\|/, $o[0];
  10         44  
  2         9  
243 8   100     34 $o[1] //= '';
244              
245 8         11 my $l = length $o[0];
246 8 100       19 $len = $l if $l > $len;
247 8         21 push @options, \@o;
248             }
249              
250 3         8 return "Options:\n" . join('', map { sprintf " %-${len}s %s\n", @$_ } @options) . "\n";
  8         71  
251             }
252              
253             sub _usage_for_subcommands {
254 4     4   11 my ($subcommands) = @_;
255 4 100       28 return '' unless @$subcommands;
256              
257 1         5 my ($len, @cmds) = (0);
258 1         6 for my $s (@$subcommands) {
259 5         10 my $l = length $s->[0];
260 5 100       11 $len = $l if $l > $len;
261 5   50     15 push @cmds, [$s->[0], $s->[2] // ''];
262             }
263              
264 1         7 return "Subcommands:\n" . join('', map { sprintf " %-${len}s %s\n", @$_ } @cmds) . "\n";
  5         30  
265             }
266              
267             1;
268              
269             =encoding utf8
270              
271             =head1 NAME
272              
273             Getopt::App - Write and test your script with ease
274              
275             =head1 SYNOPSIS
276              
277             =head2 The script file
278              
279             #!/usr/bin/env perl
280             package My::Script;
281             use Getopt::App -complete, -signatures;
282              
283             # See "APPLICATION METHODS"
284             sub getopt_post_process_argv ($app, $argv, $state) { ... }
285             sub getopt_configure ($app) { ... }
286              
287             # run() must be the last statement in the script
288             run(
289              
290             # Specify your Getopt::Long options and optionally a help text
291             'h|help # Output help',
292             'v+ # Verbose output',
293             'name=s # Specify a name',
294             'completion-script # Print autocomplete script',
295              
296             # Here is the main sub that will run the script
297             sub ($app, @extra) {
298             return print generate_completion_script() if $app->{'completion-script'};
299             return print extract_usage() if $app->{h};
300             say $app->{name} // 'no name'; # Access command line options
301             return 42; # Reture value is used as exit code
302             }
303             );
304              
305             =head2 Running the script
306              
307             The example script above can be run like any other script:
308              
309             $ my-script --name superwoman; # prints "superwoman"
310             $ echo $? # 42
311              
312             =head2 Testing
313              
314             use Test::More;
315             use Cwd qw(abs_path);
316             use Getopt::App -capture;
317              
318             # Sourcing the script returns a callback
319             my $app = do(abs_path('./bin/myapp'));
320              
321             # The callback can be called with any @ARGV
322             subtest name => sub {
323             my $got = capture($app, [qw(--name superwoman)]);
324             is $got->[0], "superwoman\n", 'stdout';
325             is $got->[1], '', 'stderr';
326             is $got->[2], 42, 'exit value';
327             };
328              
329             done_testing;
330              
331             =head2 Subcommands
332              
333             #!/usr/bin/env perl
334             # Define a package to avoid mixing methods after loading the subcommand script
335             package My::App::main;
336             use Getopt::App -complete;
337              
338             # getopt_subcommands() is called by Getopt::App
339             sub getopt_subcommands {
340             my $app = shift;
341              
342             return [
343             ['find', '/path/to/subcommand/find.pl', 'Find things'],
344             ['update', '/path/to/subcommand/update.pl', 'Update things'],
345             ];
346             }
347              
348             # run() is only called if there are no matching sub commands
349             run(
350             'h # Print help',
351             'completion-script # Print autocomplete script',
352             sub {
353             my ($app, @args) = @_;
354             return print generate_completion_script() if $app->{'completion-script'};
355             return print extract_usage();
356             }
357             );
358              
359             See L and L
360             for more details.
361              
362             =head1 DESCRIPTION
363              
364             L is a module that helps you structure your scripts and integrates
365             L with a very simple API. In addition it makes it very easy to
366             test your script, since the script file can be sourced without actually being
367             run.
368              
369             L also supports infinite nested L
370             and a method for L this module with your script to prevent
371             depending on a module from CPAN.
372              
373             =head1 APPLICATION METHODS
374              
375             These methods are optional, but can be defined in your script to override the
376             default behavior.
377              
378             =head2 getopt_complete_reply
379              
380             $app->getopt_complete_reply;
381              
382             This method will be called instead of the L callback when the
383             C and C environment variables are set. The default
384             implementation will call L.
385              
386             See also "Completion" under L.
387              
388             =head2 getopt_configure
389              
390             @configure = $app->getopt_configure;
391              
392             This method can be defined if you want L to be set up
393             differently. The default return value is:
394              
395             qw(bundling no_auto_abbrev no_ignore_case pass_through require_order)
396              
397             The default return value is currently EXPERIMENTAL.
398              
399             =head2 getopt_load_subcommand
400              
401             $code = $app->getopt_load_subcommand($subcommand, [@ARGV]);
402              
403             Takes the subcommand found in the L list and the command
404             line arguments and must return a CODE block. The default implementation is
405             simply:
406              
407             $code = do($subcommand->[1]);
408              
409             =head2 getopt_post_process_argv
410              
411             $bool = $app->getopt_post_process_argv([@ARGV], {%state});
412              
413             This method can be used to post process the options. C<%state> contains a key
414             "valid" which is true or false, depending on the return value from
415             L.
416              
417             This method can C and optionally set C<$!> to avoid calling the function
418             passed to L.
419              
420             The default behavior is to check if the first item in C<$argv> starts with a
421             hyphen, and C with an error message if so:
422              
423             Invalid argument or argument order: @$argv\n
424              
425             =head2 getopt_post_process_exit_value
426              
427             $exit_value = $app->getopt_post_process_exit_value($exit_value);
428              
429             A method to be called after the L function has been called.
430             C<$exit_value> holds the return value from L which could be any value,
431             not just 0-255. This value can then be changed to change the exit value from
432             the program.
433              
434             sub getopt_post_process_exit_value ($app, $exit_value) {
435             return int(1 + rand 10);
436             }
437              
438             =head2 getopt_pre_process_argv
439              
440             $app->getopt_pre_process_argv($argv);
441              
442             This method can be defined to pre-process C<$argv> before it is passed on to
443             L. Example:
444              
445             sub getopt_pre_process_argv ($app, $argv) {
446             $app->{first_non_option} = shift @$argv if @$argv and $argv->[0] =~ m!^[a-z]!;
447             }
448              
449             This method can C and optionally set C<$!> to avoid calling the actual
450             L function.
451              
452             =head2 getopt_subcommands
453              
454             $subcommands = $app->getopt_subcommands;
455              
456             This method must be defined in the script to enable sub commands. The return
457             value must be either C to disable subcommands or an array-ref of
458             array-refs like this:
459              
460             [["subname", "/abs/path/to/sub-command-script", "help text"], ...]
461              
462             The first element in each array-ref "subname" will be matched against the first
463             argument passed to the script, and when matched the "sub-command-script" will
464             be sourced and run inside the same perl process. The sub command script must
465             also use L for this to work properly.
466              
467             The sub-command will have C<$Getopt::App::SUBCOMMAND> set to the item found in
468             the list.
469              
470             See L for a working
471             example.
472              
473             =head2 getopt_unknown_subcommand
474              
475             $exit_value = $app->getopt_unknown_subcommand($argv);
476              
477             Will be called when L is defined but C<$argv> does not
478             match an item in the list. Default behavior is to C with an error message:
479              
480             Unknown subcommand: $argv->[0]\n
481              
482             Returning C instead of dying or a number (0-255) will cause the L
483             callback to be called.
484              
485             =head1 EXPORTED FUNCTIONS
486              
487             =head2 capture
488              
489             use Getopt::App -capture;
490             my $app = do '/path/to/bin/myapp';
491             my $array_ref = capture($app, [@ARGV]); # [$stdout, $stderr, $exit_value]
492              
493             Used to run an C<$app> and capture STDOUT, STDERR and the exit value in that
494             order in C<$array_ref>. This function will also capture C. C<$@> will be
495             set and captured in the second C<$array_ref> element, and C<$exit_value> will
496             be set to C<$!>.
497              
498             =head2 extract_usage
499              
500             # Default to "SYNOPSIS" from current file
501             my $str = extract_usage($section, $file);
502             my $str = extract_usage($section);
503             my $str = extract_usage();
504              
505             Will extract a C<$section> from POD C<$file> and append command line option
506             descriptions when called from inside of L. Command line options can
507             optionally have a description with "spaces-hash-spaces-description", like this:
508              
509             run(
510             'o|option # Some description',
511             'v|verbose # Enable verbose output',
512             sub {
513             ...
514             },
515             );
516              
517             This function will I be exported if a function with the same name already
518             exists in the script.
519              
520             =head2 new
521              
522             my $obj = new($class, %args);
523             my $obj = new($class, \%args);
524              
525             This function is exported into the caller package so we can construct a new
526             object:
527              
528             my $app = Application::Class->new(\%args);
529              
530             This function will I be exported if a function with the same name already
531             exists in the script.
532              
533             =head2 run
534              
535             # Run a code block on valid @ARGV
536             run(@rules, sub ($app, @extra) { ... });
537              
538             # For testing
539             my $cb = run(@rules, sub ($app, @extra) { ... });
540             my $exit_value = $cb->([@ARGV]);
541              
542             L can be used to call a callback when valid command line options is
543             provided. On invalid arguments, warnings will be issued and the program exit
544             with C<$?> set to 1.
545              
546             C<$app> inside the callback is a hash blessed to the caller package. The keys
547             in the hash are the parsed command line options, while C<@extra> is the extra
548             unparsed command line options.
549              
550             C<@rules> are the same options as L can take. Example:
551              
552             # app.pl -vv --name superwoman -o OptX cool beans
553             run(qw(h|help v+ name=s o=s@), sub ($app, @extra) {
554             die "No help here" if $app->{h};
555             warn $app->{v}; # 2
556             warn $app->{name}; # "superwoman"
557             warn @{$app->{o}}; # "OptX"
558             warn @extra; # "cool beans"
559             return 0; # Used as exit code
560             });
561              
562             In the example above, C<@extra> gets populated, since there is a non-flag value
563             "cool" after a list of valid command line options.
564              
565             =head1 METHODS
566              
567             =head2 bundle
568              
569             Getopt::App->bundle($path_to_script);
570             Getopt::App->bundle($path_to_script, $fh);
571              
572             This method can be used to combine L and C<$path_to_script> into a
573             a single script that does not need to have L installed from CPAN.
574             This is for example useful for sysadmin scripts that otherwise only depends on
575             core Perl modules.
576              
577             The script will be printed to C<$fh>, which defaults to C.
578              
579             Example usage:
580              
581             perl -MGetopt::App -e'Getopt::App->bundle(shift)' ./src/my-script.pl > ./bin/my-script;
582              
583             =head2 import
584              
585             use Getopt::App;
586             use Getopt::App 'My::Script::Base', -signatures;
587             use Getopt::App -capture;
588              
589             =over 2
590              
591             =item * Default
592              
593             use Getopt::App;
594              
595             Passing in no flags will export the default functions L,
596             L and L. In addition it will save you from a lot of typing, since
597             it will also import the following:
598              
599             use strict;
600             use warnings;
601             use utf8;
602             use feature ':5.16';
603              
604             =item * Completion
605              
606             use Getopt::App -complete;
607              
608             Same as L, but will also load L and import
609             L.
610              
611             =item * Signatures
612              
613             use Getopt::App -signatures;
614              
615             Same as L, but will also import L. This
616             requires Perl 5.20+.
617              
618             =item * Class name
619              
620             package My::Script::Foo;
621             use Getopt::App 'My::Script';
622              
623             Same as L but will also make C inherit from
624             L. Note that a package definition is required.
625              
626             =item * Capture
627              
628             use Getopt::App -capture;
629              
630             This will only export L.
631              
632             =back
633              
634             =head1 COPYRIGHT AND LICENSE
635              
636             This library is free software. You can redistribute it and/or modify it under
637             the same terms as Perl itself.
638              
639             =head1 AUTHOR
640              
641             Jan Henning Thorsen - C
642              
643             =cut