File Coverage

blib/lib/Getopt/EX/Module.pm
Criterion Covered Total %
statement 232 305 76.0
branch 67 112 59.8
condition 17 36 47.2
subroutine 45 53 84.9
pod 14 25 56.0
total 375 531 70.6


line stmt bran cond sub pod time code
1             package Getopt::EX::Module;
2              
3             our $VERSION = "3.03";
4              
5 9     9   102 use v5.14;
  9         53  
6 9     9   65 use warnings;
  9         28  
  9         436  
7 9     9   116 use Carp;
  9         16  
  9         560  
8              
9 9     9   43 use Exporter 'import';
  9         13  
  9         657  
10             our @EXPORT = qw();
11             our %EXPORT_TAGS = ( );
12             our @EXPORT_OK = qw();
13              
14 9     9   68 use Data::Dumper;
  9         16  
  9         444  
15 9     9   3947 use Text::ParseWords qw(shellwords);
  9         13564  
  9         682  
16 9     9   54 use List::Util qw(first pairmap);
  9         12  
  9         556  
17              
18 9     9   3921 use Getopt::EX::Func qw(parse_func);
  9         22  
  9         5992  
19              
20             sub new {
21 22     22 1 65 my $class = shift;
22 22         252 my $obj = bless {
23             Module => undef,
24             Base => undef,
25             Mode => { FUNCTION => 0, WILDCARD => 0 },
26             Define => [],
27             Expand => [],
28             Option => [],
29             Builtin => [],
30             Automod => [],
31             Autoload => {},
32             Call => [],
33             Help => [],
34             }, $class;
35              
36 22 50       108 $obj->configure(@_) if @_;
37              
38 12         34 $obj;
39             }
40              
41             sub configure {
42 22     22 1 31 my $obj = shift;
43 22         74 my %opt = @_;
44              
45 22 50       63 if (my $base = delete $opt{BASECLASS}) {
46 22         56 $obj->{Base} = $base;
47             }
48              
49 22 100       117 if (my $file = delete $opt{FILE}) {
    50          
50 2 50   2   67 open my $fh, "<:encoding(utf8)", $file
  2         1378  
  2         26  
  2         9  
51             or croak "Can't open file '$file': $!";
52 2         1906 $obj->module($file);
53 2         7 $obj->readrc($fh);
54             }
55             elsif (my $module = delete $opt{MODULE}) {
56 20   50     86 my $pkg = $opt{PACKAGE} || 'main';
57 20         90 my @base = do {
58 20 100       56 if (ref $obj->{Base} eq 'ARRAY') {
59 2         2 @{$obj->{Base}};
  2         7  
60             } else {
61 18   50     56 ($obj->{Base} // '');
62             }
63             };
64 20         58 while (@base) {
65 23         37 my $base = shift @base;
66 23 100       64 my $mod = $base ? "$base\::$module" : $module;
67 23         110 my $path = $mod =~ s{::}{/}gr . ".pm";
68 23     5   2707 eval "package $pkg; use $mod;";
  5     5   797  
  0     2   0  
  0     2   0  
  5     2   2188  
  5     2   1051  
  5     2   104  
  2     1   269  
  0     1   0  
  0     1   0  
  2         740  
  2         379  
  2         74  
  2         299  
  1         170  
  1         12  
  2         429  
  0         0  
  0         0  
  2         317  
  0         0  
  0         0  
  1         108  
  1         185  
  1         12  
  1         871  
  0         0  
  0         0  
  1         125  
  1         183  
  1         11  
69 23 100       135 if ($@) {
70 13 100 66     93 next if @base and $@ =~ /Can't locate \Q$path\E/;
71 10         2041 croak "$mod: $@";
72             }
73 10         40 $obj->module($mod);
74 10         49 $obj->define('__PACKAGE__' => $mod);
75 10         39 local *data = "$mod\::DATA";
76 10 50       58 if (not eof *data) {
77 10         21 my $pos = tell *data;
78 10         36 $obj->readrc(*data);
79             # recover position in case called multiple times
80 10 50 50     141 seek *data, $pos, 0 or die "seek: $!" if $pos >= 0;
81             }
82 10         31 last;
83             }
84             }
85              
86 12 50       37 if (my $builtin = delete $opt{BUILTIN}) {
87 0         0 $obj->builtin(@$builtin);
88             }
89              
90 12 50       31 warn "Unprocessed option: ", Dumper \%opt if %opt;
91              
92 12         57 $obj;
93             }
94              
95             sub readrc {
96 12     12 0 29 my $obj = shift;
97 12         27 my $fh = shift;
98 12         16 my $text = do { local $/; <$fh> };
  12         40  
  12         343  
99 12         66 for ($text) {
100 12 50       58 s/^__(?:CODE|PERL5?)__\s*\n(.*)//ms and do {
101             package main;
102 9     9   67 no warnings 'once';
  9         12  
  9         5281  
103 0         0 local $main::MODULE = $obj;
104 0         0 eval $1;
105 0 0       0 die if $@;
106             };
107 12         121 s/^\s*(?:#.*)?\n//mg;
108 12         33 s/\\\n//g;
109             }
110 12         42 $obj->parsetext($text);
111 12         52 $obj;
112             }
113              
114             ############################################################
115              
116             sub module {
117 67     67 1 87 my $obj = shift;
118             @_ ? $obj->{Module} = shift
119 67 100 50     267 : $obj->{Module} // '';
120             }
121              
122             sub title {
123 0     0 0 0 my $obj = shift;
124 0         0 my $mod = $obj->module;
125 0 0       0 $mod =~ m{ .* [:/] (.+) }x ? $1 : $mod;
126             }
127              
128             sub define {
129 18     18 1 24 my $obj = shift;
130 18         39 my $name = shift;
131 18         26 my $list = $obj->{Define};
132 18 50       33 if (@_) {
133 18         235 my $re = qr/\Q$name/;
134 18         63 unshift(@$list, [ $name, $re, shift ]);
135             } else {
136 0     0   0 first { $_->[0] eq $name } @$list;
  0         0  
137             }
138             }
139              
140             sub expand {
141 101     101 1 95 my $obj = shift;
142 101         130 local *_ = shift;
143 101         227 for my $defent (@{$obj->{Define}}) {
  101         129  
144 107         160 my($name, $re, $string) = @$defent;
145 107         337 s/$re/$string/g;
146             }
147 101   0     212 s{ (\$ENV\{ (['"]?) \w+ \g{-1} \}) }{ eval($1) // $1 }xge;
  0         0  
148             }
149              
150             sub mode {
151 40     40 1 50 my $obj = shift;
152 40 100       155 @_ == 1 and return $obj->{Mode}->{uc shift};
153 2 50       18 die "Unexpected parameter." if @_ % 2;
154             pairmap {
155 2     2   22 $obj->{Mode}->{uc $a} = $b;
156 2         24 } @_;
157             }
158              
159 9     9   55 use constant BUILTIN => "__BUILTIN__";
  9         12  
  9         18024  
160 28     28 0 71 sub validopt { $_[0] ne BUILTIN }
161              
162             sub setlocal {
163 0     0 1 0 my $obj = shift;
164 0         0 $obj->setlist("Expand", @_);
165             }
166              
167             sub setopt {
168 101     101 1 124 my $obj = shift;
169 101         160 $obj->setlist("Option", @_);
170             }
171              
172             sub setlist {
173 101     101 0 148 my $obj = shift;
174 101         128 my $list = $obj->{+shift};
175 101         108 my $name = shift;
176 101         125 my @args = do {
177 101 50       125 if (ref $_[0] eq 'ARRAY') {
178 0         0 @{ $_[0] };
  0         0  
179             } else {
180 101         184 map { shellwords $_ } @_;
  101         212  
181             }
182             };
183              
184 101         4785 for (my $i = 0; $i < @args; $i++) {
185 101 50       176 if (my @opt = $obj->getlocal($args[$i])) {
186 0         0 splice @args, $i, 1, @opt;
187 0         0 redo;
188             }
189             }
190              
191 101         146 for (@args) {
192 101         152 $obj->expand(\$_);
193             }
194 101         233 unshift @$list, [ $name, @args ];
195             }
196              
197             sub getopt {
198 118     118 1 117 my $obj = shift;
199 118         175 my($name, %opt) = @_;
200 118 50 33     273 return () if $name eq 'default' and not $opt{DEFAULT} || $opt{ALL};
      66        
201              
202 118         141 my $list = $obj->{Option};
203             my $e = first {
204 910 100 66 910   1208 $_->[0] eq $name and $opt{ALL} || validopt($_->[1])
205 118         347 } @$list;
206 118 100       347 my @e = $e ? @$e : ();
207 118         128 shift @e;
208              
209             # check autoload
210 118 100       168 unless (@e) {
211 99         123 my $hash = $obj->{Autoload};
212 99         95 for my $mod (@{$obj->{Automod}}) {
  99         151  
213 0 0       0 if (exists $hash->{$mod}->{$name}) {
214 0         0 delete $hash->{$mod};
215 0         0 return ($mod, $name);
216             }
217             }
218             }
219              
220 118         229 @e;
221             }
222              
223             sub getlocal {
224 101     101 0 99 my $obj = shift;
225 101         135 my($name, %opt) = @_;
226              
227 101     0   247 my $e = first { $_->[0] eq $name } @{$obj->{Expand}};
  0         0  
  101         209  
228 101 50       265 my @e = $e ? @$e : ();
229 101         102 shift @e;
230 101         251 @e;
231             }
232              
233             sub expand_args {
234 19     19 0 27 my $obj = shift;
235 19         51 my @args = @_;
236              
237             ##
238             ## Expand `&function' style arguments.
239             ##
240 19 100       42 if ($obj->mode('function')) {
241             @args = map {
242 1 50       3 if (/^&(.+)/) {
  1         16  
243 1         3 my $func = parse_func $obj->module . "::$1";
244 1 50       13 $func ? $func->call : $_;
245             } else {
246 0         0 $_;
247             }
248             }
249             @args;
250             }
251              
252             ##
253             ## Expand wildcards.
254             ##
255 19 100       57 if ($obj->mode('wildcard')) {
256             @args = map {
257 4         10 my @glob = glob $_;
  4         452  
258 4 100       33 @glob ? @glob : $_;
259             } @args;
260             }
261              
262 19         47 @args;
263             }
264              
265             sub default {
266 12     12 1 16 my $obj = shift;
267 12         33 $obj->getopt('default', DEFAULT => 1);
268             }
269              
270             sub options {
271 0     0 1 0 my $obj = shift;
272 0         0 my $opt = $obj->{Option};
273 0         0 my $automod = $obj->{Automod};
274 0         0 my $auto = $obj->{Autoload};
275 0         0 my @opt = reverse map { $_->[0] } @$opt;
  0         0  
276 0         0 my @auto = map { sort keys %{$auto->{$_}} } @$automod;
  0         0  
  0         0  
277 0         0 (@opt, @auto);
278             }
279              
280             sub help {
281 0     0 1 0 my $obj = shift;
282 0         0 my $name = shift;
283 0         0 my $list = $obj->{Help};
284 0 0       0 if (@_) {
285 0         0 unshift(@$list, [ $name, shift ]);
286             } else {
287 0     0   0 my $e = first { $_->[0] eq $name } @$list;
  0         0  
288 0 0       0 $e ? $e->[1] : undef;
289             }
290             }
291              
292             sub parsetext {
293 12     12 0 17 my $obj = shift;
294 12         16 my $text = shift;
295 12         67 my $re = qr{
296             (?|
297             # HERE document
298             (.+\s) << (?\w+) \n
299             (? (?s:.*?) \n )
300             \g{mark}\n
301             |
302             (.+)\n?
303             )
304             }x;
305 12         111 while ($text =~ m/$re/g) {
306 111         111 my $line = do {
307 111 50       367 if (defined $+{here}) {
308 0         0 $1 . $+{here};
309             } else {
310 111         200 $1;
311             }
312             };
313 111         205 $obj->parseline($line);
314             }
315 12         33 $obj;
316             }
317              
318             sub parseline {
319 111     111 0 133 my $obj = shift;
320 111         128 my $line = shift;
321 111         212 my @arg = split ' ', $line, 3;
322              
323 111         203 my %min_args = ( mode => 1, DEFAULT => 3 );
324 111   66     298 my $min_args = $min_args{$arg[0]} || $min_args{DEFAULT};
325 111 50       194 if (@arg < $min_args) {
326 0         0 warn sprintf("Parse error in %s: %s\n", $obj->title, $line);
327 0         0 return;
328             }
329              
330             ##
331             ## in-line help document after //
332             ##
333 111   50     175 my $optname = $arg[1] // '';
334 111 100       167 if ($arg[0] eq "builtin") {
335 32         42 for ($optname) {
336 32         87 s/[^\w\-].*//; # remove alternative names after `|'.
337 32 50       86 s/^(?=([\w\-]+))/length($1) == 1 ? '-' : '--'/e;
  32         98  
338             }
339             }
340 111 50 66     304 if ($arg[2] and $arg[2] =~ s{ (?:^|\s+) // \s+ (?.*) }{}x) {
341 0         0 $obj->help($optname, $+{message});
342             }
343              
344             ##
345             ## Commands
346             ##
347 111 100       258 if ($arg[0] eq "define") {
    100          
    50          
    50          
    100          
    50          
    50          
    0          
348 8         21 $obj->define($arg[1], $arg[2]);
349             }
350             elsif ($arg[0] eq "option") {
351 69         111 $obj->setopt($arg[1], $arg[2]);
352             }
353             elsif ($arg[0] eq "expand") {
354 0         0 $obj->setlocal($arg[1], $arg[2]);
355             }
356             elsif ($arg[0] eq "defopt") {
357 0         0 $obj->define($arg[1], $arg[2]);
358 0         0 $obj->setopt($arg[1], $arg[1]);
359             }
360             elsif ($arg[0] eq "builtin") {
361 32         63 $obj->setopt($optname, BUILTIN);
362 32 50       103 if ($arg[2] =~ /^\\?(?[\$\@\%\&])(?[\w:]+)/) {
363 32         176 my($mark, $name) = @+{"mark", "name"};
364 32         70 my $mod = $obj->module;
365 32   33     151 /:/ or s/^/$mod\::/ for $name;
366 9     9   68 no strict 'refs';
  9         13  
  9         6343  
367 32         84 $obj->builtin($arg[1] => {'$' => \${$name},
368 32         67 '@' => \@{$name},
369 32         57 '%' => \%{$name},
370 32         45 '&' => \&{$name}}->{$mark});
  32         136  
371             }
372             }
373             elsif ($arg[0] eq "autoload") {
374 0         0 shift @arg;
375 0         0 $obj->autoload(@arg);
376             }
377             elsif ($arg[0] eq "mode") {
378 2         5 shift @arg;
379 2         7 for (@arg) {
380 2 50       11 if (/^(no-?)?(.*)/i) {
381 2 50       33 $obj->mode($2 => $1 ? 0 : 1);
382             }
383             }
384             }
385             elsif ($arg[0] eq "help") {
386 0         0 $obj->help($arg[1], $arg[2]);
387             }
388             else {
389 0         0 warn sprintf("Unknown operator \"%s\" in %s\n",
390             $arg[0], $obj->title);
391             }
392              
393 111         735 $obj;
394             }
395              
396             sub builtin {
397 36     36 1 39 my $obj = shift;
398 36         42 my $list = $obj->{Builtin};
399 36 100       126 @_ ? push @$list, @_
400             : @$list;
401             }
402              
403             sub autoload {
404 0     0 1 0 my $obj = shift;
405 0         0 my $module = shift;
406 0         0 my @option = map { split ' ' } @_;
  0         0  
407              
408 0   0     0 my $hash = ($obj->{Autoload}->{$module} //= {});
409 0         0 my $list = $obj->{Automod};
410 0         0 for (@option) {
411 0         0 $hash->{$_} = 1;
412 0         0 $obj->help($_, "autoload: $module");
413             }
414 0 0       0 push @$list, $module if not grep { $_ eq $module } @$list;
  0         0  
415             }
416              
417             sub call {
418 11     11 0 16 my $obj = shift;
419 11         27 my $list = $obj->{Call};
420 11 50       38 @_ ? push @$list, @_
421             : @$list;
422             }
423              
424             sub call_if_defined {
425 22     22 0 51 my($module, $name, @param) = @_;
426 22         37 my $func = "$module\::$name";
427 22 100       148 if (defined &$func) {
428 9     9   74 no strict 'refs';
  9         13  
  9         1907  
429 5         23 $func->(@param);
430             }
431             }
432              
433             sub run_inits {
434 11     11 0 16 my $obj = shift;
435 11         19 my $argv = shift;
436 11         27 my $module = $obj->module;
437 11         30 local @ARGV = ();
438              
439 11         50 call_if_defined $module, "initialize" => ($obj, $argv);
440              
441 11         44 for my $call ($obj->call) {
442 0 0       0 my $func = $call->can('call') ? $call : parse_func($call);
443 0         0 $func->call;
444             }
445              
446 11         37 call_if_defined $module, "finalize" => ($obj, $argv);
447             }
448              
449             1;
450              
451             =head1 NAME
452              
453             Getopt::EX::Module - RC/Module data container
454              
455             =head1 SYNOPSIS
456              
457             use Getopt::EX::Module;
458              
459             my $bucket = Getopt::EX::Module->new(
460             BASECLASS => $baseclass,
461             FILE => $file_name / MODULE => $module_name,
462             );
463              
464             =head1 DESCRIPTION
465              
466             This module is usually used from L, and keeps
467             all data about the loaded rc file or module.
468              
469             =head2 MODULE
470              
471             After a user-defined module is loaded, the subroutine C is
472             called if it exists in the module. At this time, the container object is
473             passed to the function as the first argument and the following command
474             argument pointer as the second. So you can use it to directly access
475             the object contents through the class interface.
476              
477             Following C, the function defined with the module option is called.
478              
479             Finally, the subroutine C is called if defined, to finalize the startup
480             process of the module.
481              
482             =head2 FILE
483              
484             For rc files, the section after the C<__PERL__> or C<__PERL5__> mark is
485             executed as a Perl program. At this time, the module object is assigned to the
486             variable C<$MODULE>, and you can access the module API through it.
487              
488             if (our $MODULE) {
489             $MODULE->setopt('default', '--number');
490             }
491              
492             =head1 RC FILE FORMAT
493              
494             =over 7
495              
496             =item B
497              
498             Define option I. Argument I is processed by the
499             I routine defined in the L module. Be aware
500             that this module sometimes requires escaped backslashes.
501              
502             Any kind of string can be used for an option name but it is not combined
503             with other options.
504              
505             option --fromcode --outside='(?s)\/\*.*?\*\/'
506             option --fromcomment --inside='(?s)\/\*.*?\*\/'
507              
508             If the option named B is defined, it will be used as a
509             default option.
510              
511             For the purpose of including following arguments within replaced
512             strings, two special notations can be used in option definitions.
513              
514             The string C<< $ >> is replaced by the Ith argument after the
515             substituted option, where I is a number starting from one. Because C<<
516             $<0> >> is replaced by the defined option itself, you have to be careful
517             about infinite loops.
518              
519             The string C<< $ >> is replaced by the following command line argument
520             and the argument is removed from the list.
521              
522             For example, when
523              
524             option --line --le &line=$
525              
526             is defined, the command
527              
528             greple --line 10,20-30,40
529              
530             will be evaluated as:
531              
532             greple --le &line=10,20-30,40
533              
534             There are special arguments to manipulate option behavior and the rest
535             of the arguments. Argument C<< $ >> moves all following arguments
536             there, C<< $ >> just removes them, and C<< $ >> copies
537             them. These do not work when included as part of a string.
538              
539             They take one or two optional parameters, which are passed to the Perl
540             C function as I and I. C<< $ >> is the
541             same as C<< $ >>; C<< $ >> is the same as C<< $<1> >>;
542             C<< $ >> is the same as C<< $ >>; C<< $ >> moves
543             the last argument; C<< $move(1,1) >> moves the second argument. The next
544             example exchanges the following two arguments.
545              
546             option --exch $
547              
548             You can use the recently introduced C<< $ >> to ignore the
549             argument. Some existing modules use C<< $ >> for the same
550             purpose, because it effectively does nothing.
551              
552             option --deprecated $
553             option --deprecated $
554              
555             =item B I I
556              
557             Define local option I. The B command is almost the same as the
558             B
559             by this command are expanded in, and only in, the process of
560             definition, while option definitions are expanded when command arguments
561             are processed.
562              
563             This is similar to a string macro defined by the following B
564             command. But macro expansion is done by simple string replacement, so
565             you have to use B to define options composed of multiple
566             arguments.
567              
568             =item B I I
569              
570             Define a string macro. This is similar to B
571             not processed by I and is treated as simple text, so
572             meta-characters can be included without escaping. Macro expansion is
573             performed for option definitions and other macro definitions. Macros are not
574             evaluated in command line options. Use the option directive if you want to
575             use it in the command line,
576              
577             define (#kana) \p{InKatakana}
578             option --kanalist --nocolor -o --join --re '(#kana)+(\n(#kana)+)*'
579             help --kanalist List up Katakana string
580              
581             A here-document can be used to define strings including newlines.
582              
583             define __script__ <
584             {
585             ...
586             }
587             EOS
588              
589             The special macro C<__PACKAGE__> is pre-defined to the module name.
590              
591             =item B I
592              
593             Define a help message for option I.
594              
595             =item B I I
596              
597             Define a built-in option which should be processed by the option parser.
598             The defined option spec can be retrieved by the B method, and the script is
599             responsible for passing them to the parser.
600              
601             Arguments are assumed to be L style specs, and
602             I is a string starting with C<$>, C<@> or C<%>. They will be
603             replaced by a reference to the object which the string represents.
604              
605             =item B I I
606              
607             Define a module which should be loaded automatically when the specified
608             option is found in the command arguments.
609              
610             For example,
611              
612             autoload -Mdig --dig
613              
614             replaces the option "I<--dig>" with "I<-Mdig --dig>", and the I module is
615             loaded before processing the I<--dig> option.
616              
617             =item B [I]I
618              
619             Set or unset mode I. Currently, B and B can
620             be used as a name. See the METHODS section.
621              
622             The next example is used in the L module to
623             produce parameters on the fly.
624              
625             mode function
626             option --dyncmap &dyncmap($)
627              
628             =back
629              
630             =head1 METHODS
631              
632             =over 4
633              
634             =item B I
635              
636             Create an object. Parameters are passed to the C method.
637              
638             =item B
639              
640             Configure the object. Parameters are passed in hash name and value style.
641              
642             =over 4
643              
644             =item B =E I
645              
646             Set base class.
647              
648             =item B =E I
649              
650             Load file.
651              
652             =item B =E I
653              
654             Load module.
655              
656             =back
657              
658             =item B I, I
659              
660             Define macro.
661              
662             =item B I, I
663              
664             Set option.
665              
666             =item B I, I
667              
668             Set option which is effective only in the module.
669              
670             =item B I
671              
672             Get an option. Takes an option name and returns its definition if
673             available. It doesn't return the I option; get it by the I
674             method.
675              
676             =item B
677              
678             Get the default option. Use C ...)> to set it.
679              
680             =item B
681              
682             Get built-in options.
683              
684             =item B
685              
686             Set autoload module.
687              
688             =item B
689              
690             Set the argument treatment mode. Arguments produced by option expansion
691             will be the subject of post-processing. This method defines the behavior
692             of it.
693              
694             =over 4
695              
696             =item B(B => 1)
697              
698             Interpret arguments starting with '&' as a function, and replace them with
699             the result of the function call.
700              
701             =item B(B => 1)
702              
703             Replace wildcard arguments with matched file names.
704              
705             =back
706              
707             =back