File Coverage

blib/lib/Exporter/Easy.pm
Criterion Covered Total %
statement 115 120 95.8
branch 62 80 77.5
condition 7 11 63.6
subroutine 10 10 100.0
pod 0 4 0.0
total 194 225 86.2


line stmt bran cond sub pod time code
1             package Exporter::Easy;
2             $Exporter::Easy::VERSION = '0.18';
3 2     2   23498 use 5.006;
  2         8  
4 2     2   10 use strict;
  2         4  
  2         45  
5 2     2   9 use warnings;
  2         10  
  2         57  
6              
7             require Exporter;
8 2     2   9 use vars;
  2         4  
  2         1945  
9              
10              
11             sub import
12             {
13 13     13   12901 my $pkg = shift;
14              
15 13         32 unshift(@_, scalar caller);
16              
17             # must goto or we lose the use vars functionality
18              
19 13         36 goto &set_export_vars;
20             }
21              
22             sub set_export_vars
23             {
24             # this handles setting up all of the EXPORT variables in the callers
25             # package. It gives a nice way of creating tags, allows you to use tags
26             # when defining @EXPORT, @EXPORT_FAIL and other in tags. It also takes
27             # care of @EXPORT_OK.
28            
29 15     15 0 44 my ($callpkg, %args) = @_;
30              
31 15         18 my %could_export; # symbols that could be exported
32             my @will_export; # symbols that will be exported by default
33 0         0 my @fail; # symbols that should be tested before export
34 0         0 my @ok_only; # the symbols that are ok to export
35              
36 0         0 my %tags; # will contain a ref hash of all tags
37              
38 15         29 @_ = (); # we'll be using this for vars to be use vars'd
39              
40 15 50 66     48 if ($args{OK_ONLY} and $args{OK})
41             {
42 0         0 nice_die("Can't use OK_ONLY and OK together");
43             }
44              
45 15 100       36 my $isa = exists $args{ISA} ? delete $args{ISA} : 1;
46 15 100       31 my $vars = exists $args{VARS} ? delete $args{VARS} : 1;
47              
48 15 100       50 if (my $tag_data = delete $args{'TAGS'})
49             {
50 7 50       22 nice_die("TAGS must be a reference to an array") unless ref($tag_data) eq 'ARRAY';
51              
52 7         16 add_tags($tag_data, \%tags);
53              
54 7         15 @could_export{map {@$_} values %tags} = ();
  17         49  
55             }
56              
57 15 100       45 if (my $export = delete $args{'EXPORT'})
58             {
59 6 50       17 nice_die("EXPORT must be a reference to an array")
60             unless ref($export) eq 'ARRAY';
61            
62 6         22 @will_export = eval { expand_tags($export, \%tags) };
  6         13  
63 6 100       23 nice_die("$@while building the EXPORT list in $callpkg") if $@;
64             }
65              
66 14 100       33 if (my $ok = delete $args{'OK'})
67             {
68 4 50       13 nice_die("OK must be a reference to a array") unless ref($ok) eq 'ARRAY';
69              
70 4         7 my @ok = eval { expand_tags($ok, \%tags) };
  4         10  
71 4 50       10 nice_die("$@while building the \@EXPORT_OK") if $@;
72 4         13 @could_export{@ok} = ();
73             }
74              
75 14         22 my $ok_only = delete $args{'OK_ONLY'};
76 14 100       28 if ($ok_only)
77             {
78 3 50       15 die("OK_ONLY must be a reference to a array") unless ref($ok_only) eq 'ARRAY';
79              
80 3         5 @ok_only = eval { expand_tags($ok_only, \%tags) };
  3         7  
81 3 50       8 nice_die("$@while building the OK_ONLY list") if $@;
82              
83 3         8 @could_export{@ok_only} = ();
84             }
85              
86 14 100       31 if (my $fail = delete $args{'FAIL'})
87             {
88 2 50       6 die "FAIL must be a reference to an array" unless ref($fail) eq 'ARRAY';
89              
90 2         3 @fail = eval { expand_tags($fail, \%tags) };
  2         6  
91 2 50       5 nice_die("$@while building \@EXPORT_FAIL") if $@;
92 2         5 @could_export{@fail} = ();
93             }
94              
95 14         42 my @could_export = keys %could_export;
96              
97 14 100       39 if (defined(my $all = delete $args{'ALL'}))
98             {
99 2 50       6 nice_die("No name supplied for ALL") unless length($all);
100              
101 2 50       5 nice_die("Cannot use '$all' for ALL, already exists") if exists $tags{$all};
102              
103 2         3 my %all;
104 2         5 @all{@could_export, @will_export} = ();
105              
106 2         8 $tags{$all} = [keys %all];
107             }
108              
109 14 100       35 if ($vars)
110             {
111 13 100       30 if (my $ref = ref($vars))
112             {
113 1 50       12 nice_die("VARS was a reference to a ".$ref." instead of an array")
114             unless $ref eq 'ARRAY';
115 1         6 @_ = ('vars', grep /^(?:\$|\@|\%)/, eval { expand_tags($vars, \%tags) });
  1         3  
116 1 50       5 nice_die("$@while building the \@EXPORT") if $@;
117             }
118             else
119             {
120 12         59 @_ = ('vars', grep /^(?:\$|\@|\%)/, @will_export, @could_export);
121             }
122             }
123              
124 14 50       32 if (%args)
125             {
126 0         0 nice_die("Attempt to use unknown keys: ", join(", ", keys %args));
127             }
128              
129 2     2   22 no strict 'refs';
  2         3  
  2         1777  
130 14 100       32 if ($isa)
131             {
132 13         13 push(@{"$callpkg\::ISA"}, "Exporter");
  13         137  
133             }
134              
135 14 100       36 @{"$callpkg\::EXPORT"} = @will_export if @will_export;
  5         26  
136 14 100       37 %{"$callpkg\::EXPORT_TAGS"} = %tags if %tags;
  8         134  
137 14 100       31 @{"$callpkg\::EXPORT_OK"} = $ok_only ? @ok_only : @could_export;
  14         81  
138 14 100       32 @{"$callpkg\::EXPORT_FAIL"} = @fail if @fail;
  2         11  
139              
140 14 100       2255 if (@_ > 1)
141             {
142 3         1807 goto &vars::import;
143             }
144             }
145              
146             sub nice_die
147             {
148 1     1 0 3 my $msg = shift;
149 1   50     6 my $level = shift || 1;
150              
151 1         6 my ($pkg, $file, $line) = caller(1);
152              
153 1         15 die "$msg at $file line $line\n";
154             }
155              
156             sub add_tags($;$)
157             {
158             # this takes a reference to tag data and an optional reference to a hash
159             # of already exiting tags. If no hash ref is supplied then it creates an
160             # empty one
161            
162             # It adds the tags from the tag data to the hash ref.
163              
164 8     8 0 488 my $tag_data = shift;
165 8   100     27 my $tags = shift || {};
166              
167 8         23 my @tag_data = @$tag_data;
168 8         23 while (@tag_data)
169             {
170 20   50     47 my $tag_name = shift @tag_data || die "No name for tag";
171 20 50       43 die "Tag name cannot be a reference, maybe you left out a comma"
172             if (ref $tag_name);
173              
174             die "Tried to redefine tag '$tag_name'"
175 20 50       44 if (exists $tags->{$tag_name});
176              
177 20   50     43 my $tag_list = shift @tag_data || die "No values for tag '$tag_name'";
178              
179 20 50       50 die "Tag values for '$tag_name' is not a reference to an array"
180             unless ref($tag_list) eq 'ARRAY';
181              
182 20         25 my @symbols = eval { expand_tags($tag_list, $tags) };
  20         52  
183 20 50       49 die "$@while building tag '$tag_name'" if $@;
184              
185 20         77 $tags->{$tag_name} = \@symbols;
186             }
187              
188 8         15 return $tags;
189             }
190              
191             sub expand_tags($$)
192             {
193             # this takes a list of strings. Each string can be a symbol, or a tag and
194             # each may start with a ! to signify deletion.
195            
196             # We return a list of symbols where all the tag have been expanded and
197             # some symbols may have been deleted
198              
199             # we die if we hit an unknown tag
200              
201 40     40 0 1986 my ($string_list, $so_far) = @_;
202              
203 40         46 my %this_tag;
204              
205 40         71 foreach my $sym (@$string_list)
206             {
207 117         127 my @symbols; # list of symbols to add or delete
208 117         125 my $remove = 0;
209              
210 117 100       242 if ($sym =~ s/^!//)
211             {
212 7         11 $remove = 1;
213             }
214              
215 117 100       237 if ($sym =~ s/^://)
216             {
217 14         24 my $sub_tag = $so_far->{$sym};
218 14 100       74 die "Tried to use an unknown tag '$sym'" unless defined($sub_tag);
219              
220 13 100       24 if ($remove)
221             {
222 5         24 delete @this_tag{@$sub_tag}
223             }
224             else
225             {
226 8         32 @this_tag{@$sub_tag} = ();
227             }
228             }
229             else
230             {
231 103 100       204 if ($remove)
232             {
233 2         5 delete $this_tag{$sym};
234             }
235             else
236             {
237 101         303 $this_tag{$sym} = undef;
238             }
239             }
240             }
241              
242 39         266 return keys %this_tag;
243             }
244              
245             1;
246             __END__