File Coverage

blib/lib/Importer/Zim/Base.pm
Criterion Covered Total %
statement 88 92 95.6
branch 50 68 73.5
condition 15 25 60.0
subroutine 13 13 100.0
pod n/a
total 166 198 83.8


line stmt bran cond sub pod time code
1              
2             package Importer::Zim::Base;
3             $Importer::Zim::Base::VERSION = '0.11.0';
4             # ABSTRACT: Base module for Importer::Zim backends
5              
6 5     5   233290 use 5.010001;
  5         60  
7              
8 5     5   1645 use Module::Runtime ();
  5         7820  
  5         142  
9              
10 5     5   1411 use Importer::Zim::Utils qw(DEBUG carp croak);
  5         13  
  5         28  
11              
12             sub _prepare_args {
13 16     16   57123 my $class = shift;
14 16 50       51 my $package = shift
15             or croak qq{Usage: use $class MODULE => [\%OPTS =>] EXPORTS...\n};
16              
17 16 100       69 my $opts = _module_opts( ref $_[0] eq 'HASH' ? shift : {} );
18 16 50       42 my @version = exists $opts->{-version} ? ( $opts->{-version} ) : ();
19 16         59 &Module::Runtime::use_module( $package, @version );
20              
21 16         9236 my $can_export = _can_export($package);
22              
23 16         30 my ( @exports, %seen );
24 16 100 66     44 @_ = @{"${package}::EXPORT"} unless @_ || !${"${package}::"}{'EXPORT'};
  4         22  
  4         23  
25 16         36 while (@_) {
26 166         293 my @symbols = _expand_symbol( $package, shift );
27 166 100       385 my $opts = _import_opts( ref $_[0] eq 'HASH' ? shift : {}, $opts );
28             exists $opts->{-filter}
29 166 100       385 and @symbols = grep &{ $opts->{-filter} }, @symbols;
  144         227  
30 166         902 for my $symbol (@symbols) {
31             croak qq{"$symbol" is not exported by "$package"}
32 89 50 66     291 if $opts->{-strict} && !$can_export->{$symbol};
33 89 50       202 croak qq{Can't handle "$symbol"}
34             if $symbol =~ /^[\$\@\%\*]/;
35 89         109 my $sub = *{"${package}::${symbol}"}{CODE};
  89         237  
36 89         116 my $export = do {
37 89   66     222 local $_ = $opts->{-as} // $symbol;
38 89 100       175 exists $opts->{-map} ? $opts->{-map}->() : $_;
39             };
40 89 50       152 croak qq{Can't find "$symbol" in "$package"}
41             unless $sub;
42 89         264 my $seen = $seen{$export}{$sub}++;
43             croak qq{Can't import as "$export" twice}
44 89 50       103 if keys %{ $seen{$export} } > 1;
  89         212  
45 89 100       151 unless ($seen) {
46 87         94 warn(qq{ Importing "${package}::${symbol}" as "$export"\n})
47             if DEBUG;
48 87         386 push @exports, { export => $export, code => $sub };
49             }
50             }
51             }
52 16         125 return @exports;
53             }
54              
55             sub _module_opts {
56             state $IS_MODULE_OPTION
57 16     16   34 = { map { ; "-$_" => 1 } qw(how filter map prefix strict version) };
  24         69  
58              
59 16         44 my %opts = ( -strict => !!1 );
60 16         25 my $o = $_[0];
61 16 100       42 $opts{-strict} = !!$o->{-strict} if exists $o->{-strict};
62 16 100       37 exists $o->{-filter} and $opts{-filter} = $o->{-filter};
63             exists $o->{-map} and $opts{-map} = $o->{-map}
64 16 50 100 7   68 or exists $o->{-prefix} and $opts{-map} = sub { $o->{-prefix} . $_ };
  7   33     18  
65              
66 16 50       49 if ( my @bad = grep { !$IS_MODULE_OPTION->{$_} } keys %$o ) {
  8         38  
67 0         0 carp qq{Ignoring unknown module options (@bad)\n};
68             }
69 16         37 return \%opts;
70             }
71              
72             # $opts = _import_opts($opts1, $m_opts);
73             sub _import_opts {
74             state $IS_IMPORT_OPTION
75 166     166   210 = { map { ; "-$_" => 1 } qw(as filter map prefix strict) };
  20         67  
76              
77 166         313 my %opts = ( -strict => !!1 );
78             exists $_[1]{-filter}
79 166 100       359 and $opts{-filter} = _expand_filter( $_[1]{-filter} );
80 166 100       305 exists $_[1]{-map} and $opts{-map} = $_[1]{-map};
81 166 50       328 exists $_[1]{-strict} and $opts{-strict} = $_[1]{-strict};
82 166         190 my $o = $_[0];
83 166 100       257 $opts{-as} = $o->{-as} if exists $o->{-as};
84 166 50       243 exists $o->{-filter} and $opts{-filter} = _expand_filter( $o->{-filter} );
85             exists $o->{-map} and $opts{-map} = $o->{-map}
86 166 50 100 1   347 or exists $o->{-prefix} and $opts{-map} = sub { $o->{-prefix} . $_ };
  1   33     3  
87 166 100       232 $opts{-strict} = !!$o->{-strict} if exists $o->{-strict};
88              
89 166 50       361 if ( my @bad = grep { !$IS_IMPORT_OPTION->{$_} } keys %$o ) {
  8         21  
90 0         0 carp qq{Ignoring unknown symbol options (@bad)\n};
91             }
92 166         264 return \%opts;
93             }
94              
95             sub _expand_filter {
96 144     144   169 my $filter = shift;
97 144 100   72   383 ref $filter eq 'Regexp' ? sub {/$filter/} : $filter;
  72         282  
98             }
99              
100             sub _expand_symbol {
101 166 100 66 166   660 return $_[1] unless ref $_[1] || $_[1] =~ /^[:&]/;
102              
103 5 0       15 return map { /^&/ ? substr( $_, 1 ) : $_ } @{ $_[1] } if ref $_[1];
  0 50       0  
  0         0  
104              
105 5 100       35 return substr( $_[1], 1 ) if $_[1] =~ /^&/;
106              
107 3         11 my ( $package, $tag ) = ( $_[0], substr( $_[1], 1 ) );
108             my $symbols
109 3 50 33     4 = ${"${package}::"}{'EXPORT_TAGS'} && ${"${package}::EXPORT_TAGS"}{$tag}
110             or return $_[1];
111 3 50       7 return map { /^&/ ? substr( $_, 1 ) : $_ } @$symbols;
  6         25  
112             }
113              
114             sub _can_export {
115 16     16   23 my $package = shift;
116 16         25 my %exports;
117 16 100       21 for (
    50          
118 16         62 ( ${"${package}::"}{'EXPORT'} ? @{"${package}::EXPORT"} : () ),
  4         11  
119 16         43 ( ${"${package}::"}{'EXPORT_OK'} ? @{"${package}::EXPORT_OK"} : () )
  16         44  
120             )
121             {
122 360 100       558 my $x = /^&/ ? substr( $_, 1 ) : $_;
123 360         658 $exports{$x}++;
124             }
125 16         33 return \%exports;
126             }
127              
128 5     5   46 no Importer::Zim::Utils qw(DEBUG carp croak);
  5         13  
  5         38  
129              
130             1;
131              
132             #pod =encoding utf8
133             #pod
134             #pod =head1 DESCRIPTION
135             #pod
136             #pod "The Earth is safe once more, GIR! Now let's go destroy it!"
137             #pod – Zim
138             #pod
139             #pod No public interface.
140             #pod
141             #pod =head1 DEBUGGING
142             #pod
143             #pod You can set the C environment variable
144             #pod for get some diagnostics information printed to C.
145             #pod
146             #pod IMPORTER_ZIM_DEBUG=1
147             #pod
148             #pod =head1 SEE ALSO
149             #pod
150             #pod L
151             #pod
152             #pod =cut
153              
154             __END__