File Coverage

blib/lib/Sub/Exporter/Progressive.pm
Criterion Covered Total %
statement 77 79 97.4
branch 20 30 66.6
condition 2 5 40.0
subroutine 13 13 100.0
pod 0 1 0.0
total 112 128 87.5


line stmt bran cond sub pod time code
1             package Sub::Exporter::Progressive;
2              
3 6     6   310769 use strict;
  6         15  
  6         240  
4 6     6   35 use warnings;
  6         9  
  6         621  
5              
6             our $VERSION = '0.001011';
7              
8 6     6   42 use Carp ();
  6         14  
  6         222  
9 6     6   35 use List::Util ();
  6         9  
  6         441  
10              
11             sub import {
12 7     7   231 my ($self, @args) = @_;
13              
14 7         19 my $inner_target = caller;
15 7         19 my $export_data = sub_export_options($inner_target, @args);
16              
17 7         15 my $full_exporter;
18 6     6   29 no strict 'refs';
  6         11  
  6         771  
19 7         9 @{"${inner_target}::EXPORT_OK"} = @{$export_data->{exports}};
  7         44  
  7         17  
20 7         11 @{"${inner_target}::EXPORT"} = @{$export_data->{defaults}};
  7         34  
  7         13  
21 7         10 %{"${inner_target}::EXPORT_TAGS"} = %{$export_data->{tags}};
  7         37  
  7         18  
22 7         36 *{"${inner_target}::import"} = sub {
23 6     6   39 use strict;
  6         12  
  6         6223  
24 18     18   21477 my ($self, @args) = @_;
25              
26 18 100   21   163 if (List::Util::first { ref || !m/ \A [:-]? \w+ \z /xm } @args) {
  21 100       222  
    100          
27             Carp::croak 'your usage of Sub::Exporter::Progressive requires Sub::Exporter to be installed'
28 1 50       5 unless eval { require Sub::Exporter };
  1         9  
29 1   33     10 $full_exporter ||= Sub::Exporter::build_exporter($export_data->{original});
30              
31 1         264 goto $full_exporter;
32 19 50   19   119 } elsif (defined(my $num = List::Util::first { !ref and m/^\d/ } @args)) {
33 1         19 die "cannot export symbols with a leading digit: '$num'";
34             } else {
35 16         91 require Exporter;
36 16         72 s/ \A - /:/xm for @args;
37 16         52 @_ = ($self, @args);
38 16         7831 goto \&Exporter::import;
39             }
40 7         30 };
41 7         348 return;
42             }
43              
44             my $too_complicated = <<'DEATH';
45             You are using Sub::Exporter::Progressive, but the features your program uses from
46             Sub::Exporter cannot be implemented without Sub::Exporter, so you might as well
47             just use vanilla Sub::Exporter
48             DEATH
49              
50             sub sub_export_options {
51 7     7 0 17 my ($inner_target, $setup, $options) = @_;
52              
53 7         11 my @exports;
54             my @defaults;
55 0         0 my %tags;
56              
57 7 50       32 if ($setup eq '-setup') {
58 7         76 my %options = %$options;
59              
60             OPTIONS:
61 7         24 for my $opt (keys %options) {
62 13 100       45 if ($opt eq 'exports') {
    50          
63              
64 7 50       31 Carp::croak $too_complicated if ref $options{exports} ne 'ARRAY';
65 7         15 @exports = @{$options{exports}};
  7         19  
66 7 50   18   80 Carp::croak $too_complicated if List::Util::first { ref } @exports;
  18         97  
67              
68             } elsif ($opt eq 'groups') {
69 6         13 %tags = %{$options{groups}};
  6         24  
70 6         15 for my $tagset (values %tags) {
71 11 50   12   30 Carp::croak $too_complicated if List::Util::first { / \A - (?! all \b ) /x || ref } @{$tagset};
  12 50       174  
  11         45  
72             }
73 6 50       14 @defaults = @{$tags{default} || [] };
  6         32  
74             } else {
75 0         0 Carp::croak $too_complicated;
76             }
77             }
78 7 100       22 @{$_} = map { / \A [:-] all \z /x ? @exports : $_ } @{$_} for \@defaults, values %tags;
  18         50  
  18         57  
  18         30  
79 7   50     49 $tags{all} ||= [ @exports ];
80 7         9 my %exports = map { $_ => 1 } @exports;
  18         86  
81 7         16 my @errors = grep { not $exports{$_} } @defaults;
  7         21  
82 7 50       55 Carp::croak join(', ', @errors) . " is not exported by the $inner_target module\n" if @errors;
83             }
84              
85             return {
86 7         37 exports => \@exports,
87             defaults => \@defaults,
88             original => $options,
89             tags => \%tags,
90             };
91             }
92              
93             1;
94              
95             =encoding utf8
96              
97             =head1 NAME
98              
99             Sub::Exporter::Progressive - Only use Sub::Exporter if you need it
100              
101             =head1 SYNOPSIS
102              
103             package Syntax::Keyword::Gather;
104              
105             use Sub::Exporter::Progressive -setup => {
106             exports => [qw( break gather gathered take )],
107             groups => {
108             default => [qw( break gather gathered take )],
109             },
110             };
111              
112             # elsewhere
113              
114             # uses Exporter for speed
115             use Syntax::Keyword::Gather;
116              
117             # somewhere else
118              
119             # uses Sub::Exporter for features
120             use Syntax::Keyword::Gather 'gather', take => { -as => 'grab' };
121              
122             =head1 DESCRIPTION
123              
124             L is an incredibly powerful module, but with that power comes
125             great responsibility, er- as well as some runtime penalties. This module
126             is a C wrapper that will let your users just use L
127             if all they are doing is picking exports, but use C if your
128             users try to use C's more advanced features, like
129             renaming exports, if they try to use them.
130              
131             Note that this module will export C<@EXPORT>, C<@EXPORT_OK> and
132             C<%EXPORT_TAGS> package variables for C to work. Additionally, if
133             your package uses advanced C features like currying, this module
134             will only ever use C, so you might as well use it directly.
135              
136             =head1 AUTHOR
137              
138             frew - Arthur Axel Schmidt (cpan:FREW)
139              
140             =head1 CONTRIBUTORS
141              
142             ilmari - Dagfinn Ilmari MannsÃ¥ker (cpan:ILMARI)
143              
144             mst - Matt S. Trout (cpan:MSTROUT)
145              
146             leont - Leon Timmermans (cpan:LEONT)
147              
148             =head1 COPYRIGHT
149              
150             Copyright (c) 2012 the Sub::Exporter::Progressive L and
151             L as listed above.
152              
153             =head1 LICENSE
154              
155             This library is free software and may be distributed under the same terms
156             as perl itself.
157              
158             =cut