Fix '-all' option for the default group
[p5sagit/Sub-Exporter-Progressive.git] / lib / Sub / Exporter / Progressive.pm
1 package Sub::Exporter::Progressive;
2
3 # ABSTRACT: Only use Sub::Exporter if you need it
4
5 use strict;
6 use warnings;
7
8 # VERSION
9
10 use List::Util 'first';
11
12 sub import {
13    my ($self, @args) = @_;
14
15    my $inner_target = caller(0);
16    my ($TOO_COMPLICATED, $export_data) = sub_export_options(@args);
17
18    if ($TOO_COMPLICATED) {
19       warn <<'WARNING';
20 You are using Sub::Exporter::Progressive, but the features your program uses from
21 Sub::Exporter cannot be implemented without Sub::Exporter, so you might as well
22 just use vanilla Sub::Exporter
23 WARNING
24       require Sub::Exporter;
25       goto \&Sub::Exporter::import;
26    }
27    else {
28       my $full_exporter;
29       no strict;
30       @{"${inner_target}::EXPORT_OK"} = @{$export_data->{exports}};
31       @{"${inner_target}::EXPORT"} = @{$export_data->{defaults}};
32       *{"${inner_target}::import"} = sub {
33          use strict;
34          my ($self, @args) = @_;
35
36          if (first { ref || !m/^\w+$/ } @args) {
37             require Sub::Exporter;
38             $full_exporter ||=
39                Sub::Exporter::build_exporter($export_data->{original});
40
41             goto $full_exporter;
42          } else {
43             require Exporter;
44             goto \&Exporter::import;
45          }
46       };
47    }
48 }
49
50 sub sub_export_options {
51    my ($setup, $options) = @_;
52
53    my $TOO_COMPLICATED = 0;
54
55    my @exports;
56    my @defaults;
57
58    if ($setup eq '-setup') {
59       my %options = %$options;
60
61       OPTIONS:
62       for my $opt (keys %options) {
63          if ($opt eq 'exports') {
64
65             $TOO_COMPLICATED = 1, last OPTIONS
66                if ref $options{exports} ne 'ARRAY';
67
68             @exports = @{$options{exports}};
69
70             $TOO_COMPLICATED = 1, last OPTIONS
71                if first { ref } @exports;
72
73          } elsif ($opt eq 'groups') {
74
75             $TOO_COMPLICATED = 1, last OPTIONS
76                if first { $_ ne 'default' } keys %{$options{groups}};
77
78             @defaults = @{$options{groups}{default} || [] };
79          } else {
80             $TOO_COMPLICATED = 1;
81             last OPTIONS
82          }
83       }
84       @defaults = @exports if $defaults[0] eq '-all';
85    }
86
87    return $TOO_COMPLICATED, {
88       exports => \@exports,
89       defaults => \@defaults,
90       original => $options,
91    }
92 }
93
94 1;
95
96 =head1 SYNOPSIS
97
98  package Syntax::Keyword::Gather;
99
100  use Sub::Exporter::Progressive -setup => {
101    exports => [qw( break gather gathered take )],
102    groups => {
103      defaults => [qw( break gather gathered take )],
104    },
105  };
106
107  # elsewhere
108
109  # uses Exporter for speed
110  use Syntax::Keyword::Gather;
111
112  # somewhere else
113
114  # uses Sub::Exporter for features
115  use Syntax::Keyword::Gather 'gather', take => { -as => 'grab' };
116
117 =head1 DESCRIPTION
118
119 L<Sub::Exporter> is an incredibly powerful module, but with that power comes
120 great responsibility, er- as well as some runtime penalties.  This module
121 is a C<Sub::Exporter> wrapper that will let your users just use L<Exporter>
122 if all they are doing is picking exports, but use C<Sub::Exporter> if your
123 users try to use C<Sub::Exporter>'s more advanced features features, like
124 renaming exports, if they try to use them.
125
126 Note that this module will export C<@EXPORT> and C<@EXPORT_OK> package
127 variables for C<Exporter> to work.  Additionally, if your package uses advanced
128 C<Sub::Exporter> features like currying, this module will only ever use
129 C<Sub::Exporter>, so you might as well use it directly.