File Coverage

blib/lib/pkg.pm
Criterion Covered Total %
statement 83 99 83.8
branch 45 60 75.0
condition 17 23 73.9
subroutine 8 11 72.7
pod n/a
total 153 193 79.2


line stmt bran cond sub pod time code
1             package pkg;
2              
3 22     22   1965635 use 5.10.1;
  22         185  
  22         1118  
4 22     22   119 use strict;
  22         43  
  22         696  
5 22     22   118 use warnings;
  22         65  
  22         27188  
6              
7             our $VERSION = '0.04';
8              
9             my %opt_nargs = (
10             alias => { n => 0, name => 'alias', value => 1, tag => 1 },
11             noalias => { n => 0, name => 'alias', value => 0 },
12             strip => { n => 1, name => 'alias', tag => 1 },
13             require => { n => 0, name => 'require', value => 1 },
14             norequire => { n => 0, name => 'require', value => 0 },
15             );
16              
17             my %mopt_nargs = (
18             as => { n => 1 },
19             import => { n => 0, last => 1 },
20             require => { n => 0, name => 'require', value => 1 },
21             norequire => { n => 0, name => 'require', value => 0 },
22             version => { n => 1 },
23             include => { n => 1 },
24             inner => { n => 0 },
25             'only_inner' => { n => 0, value => -1, name => 'inner', tag => 0 },
26             exclude => { n => 1 },
27             );
28              
29             sub import {
30              
31             # first element of @_ is just us!
32 26     26   143901 shift;
33              
34 26 100       157 return unless @_;
35              
36 25         76 my $to = caller(0);
37              
38 25         73 my %opt;
39              
40 25         98 while (@_) {
41              
42 32 50       204 if ( 'ARRAY' eq ref $_[0] ) {
    100          
43              
44 0         0 my %lopt = %opt;
45 0         0 local @_ = @{ shift @_ };
  0         0  
46              
47 0         0 unshift @_, \%lopt, \%opt_nargs, qq[global option '-%s': %s];
48 0         0 &_parse_args;
49              
50 0         0 unshift @_, $to, \%lopt;
51 0         0 &_process_pkg;
52              
53             }
54              
55             elsif ( $_[0] =~ /^-/ ) {
56              
57 7         28 unshift @_, \%opt, \%opt_nargs, qq[global option '-%s': %s];
58 7         25 &_parse_args;
59              
60             }
61              
62             else {
63 25         87 unshift @_, $to, \%opt;
64 25         66 &_process_pkg;
65 10         28 last;
66             }
67              
68             }
69              
70 10         2388 return;
71             }
72              
73             sub _process_pkg {
74              
75 25     25   73 my ( $to, $opt ) = ( shift, shift );
76              
77 25         50 my $package = shift;
78              
79 25         92 unshift @_, \my %mopt, \%mopt_nargs,
80             qq[package "$package": package option '-%s': %s];
81 25         75 &_parse_args;
82              
83 25   100     222 $mopt{require} //= $opt->{require} // 1;
      100        
84              
85             # flag indicationg everything in @_ is to be passed to pkg->import
86 25 100       86 unless ( defined $mopt{import} ) {
87              
88             # if first argument is [], duplicate standard behavior:
89             # use A (); => don't call import
90             # use A (), 'b' => A->import( 'b' );
91 23 100 66     135 if ( 'ARRAY' eq ref $_[0] && $_[0] && @{ $_[0] } == 0 ) {
  2   33     8  
92              
93 2         4 shift;
94 2         5 $mopt{import} = @_;
95             }
96             else {
97              
98 21         46 $mopt{import} = 1;
99              
100             }
101              
102             }
103              
104             # load package; this won't try to use inner packages
105 25 100       87 if ( $mopt{require} ) {
106 23         24358 require Class::Load;
107 23 50       933797 Class::Load::load_class( $package,
108             exists $mopt{version} ? { -version => $mopt{version} } : () );
109             }
110              
111 25         10596 my @packages = ($package);
112              
113 25 100       216 if ( $mopt{inner} ) {
114              
115 5         30 croak(qq[can't use option "-$_" when looping over inner packages\n])
116 5         14 for grep { defined $mopt{$_} } qw[ as ];
117              
118 5 100       33 pop @packages if $mopt{inner} < 0;
119              
120 5         4693 require Devel::InnerPackage;
121 5         20257 push @packages, Devel::InnerPackage::list_packages($package);
122             }
123              
124 25         5221 for my $pkg (@packages) {
125              
126             # print STDERR "package $pkg proferred\n";
127              
128 29 100 100     250 next if defined $mopt{include} && !( $pkg ~~ $mopt{include} );
129 27 50 66     161 next if defined $mopt{exclude} && $pkg ~~ $mopt{exclude};
130              
131             # print STDERR "package $pkg accepted\n";
132              
133 27 100 33     222 my $alias = $mopt{as} // (
134             $opt->{alias}
135             ? _dispatch_alias( $opt->{alias}, $pkg )
136             : $pkg
137             );
138              
139 27 100       132 if ( $mopt{import} ) {
140 26         21601 require Import::Into;
141 26         20678 $pkg->import::into( $to, @_ );
142             }
143              
144             # create alias if requested
145 12 50       8778 _make_alias( $to, $pkg, $alias )
146             if $pkg ne $alias;
147             }
148              
149             # all done
150 10         46 return;
151             }
152              
153             sub _make_alias {
154              
155 0     0   0 my ( $to, $package, $alias ) = @_;
156              
157 22     22   140 no strict 'refs'; ## no critic
  22         42  
  22         21147  
158 0     0   0 *{ join( '::', $to, $alias ) } = sub () { $package };
  0         0  
  0         0  
159              
160             }
161              
162             # this gets called as &_parse_args so that it alters
163             # the called @_ array
164             sub _parse_args {
165              
166 32     32   147 my ( $opts, $attr, $fmt ) = ( shift, shift, shift );
167              
168 32   100     331 while ( @_ && $_[0] =~ /^-(.*)/ ) {
169              
170 20         29 shift;
171 20         57 my $opt = $1;
172 20         91 my $attr = $attr->{$opt};
173              
174 20 50       58 _die( $fmt, $opt, 'unknown option' )
175             unless defined $attr;
176              
177 20         37 my $n = $attr->{n};
178              
179 20 50       58 _die( $fmt, $opt, 'not enough values' )
180             if @_ < $n;
181              
182 20 100       89 my $value =
    50          
    100          
183             $n == 0 ? ( exists $attr->{value} ? $attr->{value} : 1 )
184             : $n == 1 ? shift(@_)
185             : [ splice( @_, 0, $n ) ];
186              
187 20 100       53 if ( $attr->{name} ) {
188              
189 10 100       44 $opts->{ $attr->{name} } = $attr->{tag} ? [ $opt, $value ] : $value;
190             }
191              
192             else {
193              
194 10         19 $opts->{$opt} = $value;
195             }
196              
197 20 100       125 last if $attr->{last};
198             }
199              
200 32         87 return;
201             }
202              
203             sub _dispatch_alias {
204              
205 2     2   3 my ( $name, $arg ) = @{ shift() };
  2         10  
206 2         6 my $package = shift;
207              
208 2 100       10 if ( $name eq 'alias' ) {
    50          
209              
210 1 50       9 return $arg ? ( $package =~ /([^:]+)$/ )[0] : $package;
211             }
212              
213             elsif ( $name eq 'strip' ) {
214              
215 1 50       6 my %attr = 'HASH' eq ref $arg ? %{$arg} : ( pfx => $arg );
  0         0  
216              
217 1 50       4 _die("-strip: no prefix specified\n")
218             unless defined $attr{pfx};
219              
220 1         3 $attr{pfx} = quotemeta( $attr{pfx} );
221              
222 1         2 my $pfx = $attr{pfx};
223 1 50       4 my $sep = defined $attr{sep} ? quotemeta( $attr{sep} ) : '';
224              
225 1         16 ( my $npkg = $package ) =~ s/^$pfx//;
226              
227             # don't return an empty package name
228 1 50       4 return $package if $npkg eq '';
229              
230             # trim leading separator;
231 1         2 $npkg =~ s/^:://;
232 1         3 $npkg =~ s/::/$sep/g;
233              
234 1         4 return $npkg;
235             }
236              
237             else {
238              
239 0           _die("internal error");
240              
241             }
242              
243             }
244              
245             sub _die {
246              
247 0     0     require Carp;
248              
249 0 0         my $err = @_ > 1 ? sprintf( shift, @_ ) : $_[0];
250              
251 0           Carp::croak( q[error in use pkg: ], $err );
252              
253             }
254              
255             __END__