File Coverage

blib/lib/Exporter/Tidy.pm
Criterion Covered Total %
statement 35 35 100.0
branch 23 26 88.4
condition 8 10 80.0
subroutine 2 2 100.0
pod n/a
total 68 73 93.1


line stmt bran cond sub pod time code
1             package Exporter::Tidy;
2              
3             # use strict;
4             # no strict 'refs';
5              
6             # our
7             $VERSION = '0.09';
8              
9             sub import {
10 6     6   226132 my (undef, %tags) = @_;
11 6         16 my $caller = caller;
12 6         14 my $map = delete($tags{_map});
13            
14 6         11 my %available;
15 6 100       31 @available{ grep !ref, keys %$map } = () if $map;
16 6         50 @available{ grep !/^:/, map @$_, values %tags } = ();
17              
18 6   100     54 $tags{all} ||= [ keys %available ];
19              
20 6         744 *{"$caller\::import"} = sub {
21 5     5   349 my ($me, @symbols) = @_;
22 5         15 my $caller = caller;
23 5 100 100     22 @symbols = @{ $tags{default} } if @symbols == 0 and exists $tags{default};
  1         5  
24 5         10 my %exported;
25 5         10 my $prefix = '';
26 5         1980 while (my $symbol = shift @symbols) {
27 23 100       89 $symbol eq '_prefix' and ($prefix = shift @symbols, next);
28 21 100 66     65 my $real = $map && exists $map->{$symbol} ? $map->{$symbol} : $symbol;
29 21 50       61 next if exists $exported{"$prefix$real"};
30 21         43 undef $exported{"$prefix$symbol"};
31 21         30 $i++;
32             $real =~ /^:(.*)/ and (
33             (exists $tags{$1} or
34             (require Carp, Carp::croak("Unknown tag: $1"))),
35 21 100 50     72 push(@symbols, @{ $tags{$1} }),
  1         8  
36             next
37             );
38             ref $real and (
39             $symbol =~ s/^[\@\$%*]//,
40 20 100       48 *{"$caller\::$prefix$symbol"} = $real,
  5         255  
41             next
42             );
43 15 50       37 exists $available{$symbol} or
44             (require Carp, Carp::croak("Unknown symbol: $real"));
45 15         80 my ($sigil, $name) = $real =~ /^([\@\$%*]?)(.*)/;
46 15         45 $symbol =~ s/^[\@\$%*]//;
47 15         735 *{"$caller\::$prefix$symbol"} =
48 3         41 $sigil eq '' ? \&{"$me\::$name"}
49 3         10 : $sigil eq '$' ? \${"$me\::$name"}
50 3         10 : $sigil eq '@' ? \@{"$me\::$name"}
51 3         9 : $sigil eq '%' ? \%{"$me\::$name"}
52 15 50       47 : $sigil eq '*' ? \*{"$me\::$name"}
  3 100       9  
    100          
    100          
    100          
53             : (require Carp, Carp::croak("Strange symbol: $real"));
54             }
55 6         99 };
56             }
57              
58             1;
59              
60             __END__
61              
62             =head1 NAME
63              
64             Exporter::Tidy - Another way of exporting symbols
65              
66             =head1 SYNOPSIS
67              
68             package MyModule::HTTP;
69             use Exporter::Tidy
70             default => [ qw(get) ],
71             other => [ qw(post head) ];
72              
73             use MyModule::HTTP qw(:all);
74             use MyModule::HTTP qw(:default post);
75             use MyModule::HTTP qw(post);
76             use MyModule::HTTP _prefix => 'http_', qw(get post);
77             use MyModule::HTTP qw(get post), _prefix => 'http_', qw(head);
78             use MyModule::HTTP
79             _prefix => 'foo', qw(get post),
80             _prefix => 'bar', qw(get head);
81              
82             package MyModule::Foo;
83             use Exporter::Tidy
84             default => [ qw($foo $bar quux) ],
85             _map => {
86             '$foo' => \$my_foo,
87             '$bar' => \$my_bar,
88             quux => sub { print "Hello, world!\n" }
89             };
90              
91             package MyModule::Constants;
92             use Exporter::Tidy
93             default => [ qw(:all) ],
94             _map => {
95             FOO => sub () { 1 },
96             BAR => sub () { 2 },
97             OK => sub () { 1 },
98             FAILURE => sub () { 0 }
99             };
100              
101             =head1 DESCRIPTION
102              
103             This module serves as an easy, clean alternative to Exporter. Unlike Exporter,
104             it is not subclassed, but it simply exports a custom import() into your
105             namespace.
106              
107             With Exporter::Tidy, you don't need to use any package global in your
108             module. Even the subs you export can be lexically scoped.
109              
110             =head2 use Exporter::Tidy LIST
111              
112             The list supplied to C<use Exporter::Tidy> should be a key-value list. Each
113             key serves as a tag, used to group exportable symbols. The values in this
114             key-value list should be array references.
115             There are a few special tags:
116              
117             =over 10
118              
119             =item all
120              
121             If you don't provide an C<all> tag yourself, Tidy::Exporter will generate one
122             for you. It will contain all exportable symbols.
123              
124             =item default
125              
126             The C<default> tag will be used if the user supplies no list to the C<use>
127             statement.
128              
129             =item _map
130              
131             With _map you should not use an array reference, but a hash reference. Here,
132             you can rewrite symbols to other names or even define one on the spot by using
133             a reference. You can C<< foo => 'bar' >> to export C<bar> if C<foo> is
134             requested.
135              
136             =back
137              
138             =head2 Exportable symbols
139              
140             Every symbol specified in a tag's array, or used as a key in _map's
141             hash is exportable.
142              
143             =head2 Symbol types
144              
145             You can export subs, scalars, arrays, hashes and typeglobs. Do not use an
146             ampersand (C<&>) for subs. All other types must have the proper sigil.
147              
148             =head2 Importing from a module that uses Exporter::Tidy
149              
150             You can use either a symbol name (without the sigil if it is a sub, or with the
151             appropriate sigil if it is not), or a tag name prefixed with a colon. It is
152             possible to import a symbol twice, but a symbol is never exported twice under
153             the same name, so you can use tags that overlap. If you supply any list to
154             the C<use> statement, C<:default> is no longer used if not specified explicitly.
155              
156             To avoid name clashes, it is possible to have symbols prefixed. Supply
157             C<_prefix> followed by the prefix that you want. Multiple can be used.
158              
159             use Some::Module qw(foo bar), _prefix => 'some_', qw(quux);
160              
161             imports Some::Module::foo as foo, Some::Module::bar as bar, and
162             Some::Module::quux as some_quux. See the SYNOPSIS for more examples.
163              
164             =head1 COMPARISON
165              
166             Exporter::Tidy "versus" Exporter
167              
168             These numbers are valid for my Linux system with Perl 5.8.0. Your mileage may
169             vary.
170              
171             =head2 Speed
172              
173             Exporting two symbols using no import list (@EXPORT and :default) is approximately
174             10% faster with Exporter. But if you use any tag explicitly, Exporter::Tidy is
175             more than twice as fast (!) as Exporter.
176              
177             =head2 Memory usage
178              
179             perl -le'require X; print((split " ", `cat /proc/$$/stat`)[22])'
180              
181             No module 3022848
182             Exporter::Tidy 3067904
183             Exporter 3084288
184             Exporter::Heavy 3174400
185              
186             Exporter loads Exporter::Heavy automatically when needed. It is needed to
187             support exporter tags, amongst other things. Exporter::Tidy has all
188             functionality built into one module.
189              
190             Both Exporter(::Heavy) and Exporter::Tidy delay loading Carp until it is
191             needed.
192              
193             =head2 Usage
194              
195             Exporter is subclassed and gets its information from package global
196             variables like @EXPORT, @EXPORT_OK and %EXPORT_TAGS.
197              
198             Exporter::Tidy exports an C<import> method and gets its information from
199             the C<use> statement.
200              
201             =head1 LICENSE
202              
203             This software may be redistributed under the terms of the GPL, LGPL,
204             modified BSD, or Artistic license, or any of the other OSI approved
205             licenses listed at http://www.opensource.org/licenses/alphabetical.
206             Distribution is allowed under all of these licenses, or any smaller
207             subset of multiple or just one of these licenses.
208              
209             When using a packaged version, please refer to the package metadata to see
210             under which license terms it was distributed. Alternatively, a distributor
211             may choose to replace the LICENSE section of the documentation and/or
212             include a LICENSE file to reflect the license(s) they chose to redistribute
213             under.
214              
215             =head1 ACKNOWLEDGEMENTS
216              
217             Thanks to Aristotle Pagaltzis for suggesting the name Exporter::Tidy.
218              
219             =head1 AUTHOR
220              
221             Juerd Waalboer <juerd@cpan.org> <http://juerd.nl/>
222              
223             =cut