File Coverage

blib/lib/Exporter/Handy.pm
Criterion Covered Total %
statement 40 73 54.7
branch 1 16 6.2
condition 0 3 0.0
subroutine 12 18 66.6
pod 7 7 100.0
total 60 117 51.2


line stmt bran cond sub pod time code
1             package Exporter::Handy;
2              
3             # ABSTRACT: An EXPERIMENTAL subclass of , which helps create easy-to-extend modules that export symbols
4             our $VERSION = '1.000004';
5              
6 2     2   101831 use utf8;
  2         49  
  2         20  
7 2     2   105 use strict;
  2         4  
  2         46  
8 2     2   9 use warnings;
  2         3  
  2         58  
9              
10 2     2   934 use Exporter::Handy::Util qw(xtags);
  2         6  
  2         11  
11 2     2   211 use Exporter::Extensible -exporter_setup => 1;
  2         4  
  2         10  
12              
13             #=== OVERRIDES
14             sub exporter_export {
15 1     1 1 120 my $self = shift;
16 1         7 my @args = $self->_exporter_preprocess_export_args(@_);
17 1         7 $self->SUPER::exporter_export(@args)
18             }
19              
20             sub _exporter_preprocess_export_args {
21 1     1   2 my $self = shift;
22 1         4 my @args;
23 1         4 while (@_) {
24 4         6 my $arg = shift;
25 4 50       11 if ($arg eq ':') {
26 0         0 push @args, xtags( { sig => ':'}, '' => shift )
27             } else {
28 4         9 push @args, $arg
29             }
30             }
31             @args
32 1         4 }
33              
34              
35             # === EXPORT OPTIONS ====
36              
37             # PRAGMATA
38             # Remember: Pragmas effect the current compilation context.
39             # No need to keep track of where we are importing into...
40             # They require their ->import() method to be called directly, no matter how deep the call stack happens to be.
41             # Just call ->import() directly, like below, and it will do the right thing.
42 2     2 1 1201 sub strict : Export(-) { strict->import }
  2     0   1359  
  2         44  
  0         0  
43 2     2 1 1461 sub warnings : Export(-) { warnings->import }
  2     0   8  
  2         8  
  0         0  
44 2     2 1 473 sub utf8 : Export(-) { utf8->import }
  2     0   5  
  2         8  
  0         0  
45              
46             sub strictures : Export(-) {
47 0     0 1 0 strict->import;
48 0         0 warnings->import
49 2     2   523 }
  2         4  
  2         21  
50              
51             sub sane : Export(-) {
52 0     0 1 0 utf8->import;
53 0         0 strict->import;
54 0         0 warnings->import;
55 2     2   504 }
  2         4  
  2         15  
56              
57             # use Exporter::Handy qw(-sane -features), exporter_setup => 1;
58             sub features {
59 0     0 1   my ($exporter, $arg)= @_;
60              
61             # default features to turn on/off
62 0           my %feats = (
63             'current_sub' => 1, # Perl v5.16+ (2012) : enable __SUB__ token that returns a ref to the current subroutine (or undef).
64             'evalbytes' => 1, # Perl v5.16+ (2012) : like string eval, but it treats its argument as a byte string.
65             'fc' => 1, # Perl v5.16+ (2012) : enable the fc function (Unicode casefolding).
66             'lexical_subs' => 1, # Perl v5.18+ (2012) : enable declaration of subroutines via my sub foo, state sub foo and our sub foo syntax.
67             'say' => 1, # Perl v5.10+ (2007) : enable the Raku-inspired "say" function.
68             'state' => 1, # Perl v5.10+ (2007) : enable state variables.
69             'unicode_eval' => 1, # Perl v5.16+ (2012) : changes the behavior of plain string eval to work more consistently, especially in the Unicode world.
70             'unicode_strings' => 1, # Perl v5.12+ (2010) : use Unicode rules in all string operations (unless either use locale or use bytes are also within the scope).
71             );
72              
73 0           my @args = eval { @$arg }; # if $arg is an ARRAY-ref, than it denotes a list of features
  0            
74 0           my %args = eval { %$arg }; # if $arg is a HASH-ref, then it denotes individual overrides (1: on, 0:off)
  0            
75              
76 0 0         if (@args) {
77 0 0         if ($args[0] eq '+') { # request to keep defaults.
78 0           shift @args;
79 0           %args = map { $_ => 1 } @args;
  0            
80             } else { # replace defaults
81 0           %feats = map { $_ => 1 } @args;
  0            
82             }
83             }
84              
85             # handle individual overrides
86 0           %feats = (%feats, %args);
87              
88 0 0         return unless %feats;
89              
90             # determine features to be turned ON or OFF
91 0           my (@on, @off);
92 0           for (keys %feats) {
93 0 0         next if m/^-/; # ignore inline args à la , if any: -prefix, -as, ...
94              
95 0 0 0       if (defined $feats{$_} && $feats{$_}) {
96 0           push @on, $_;
97             } else {
98 0           push @off, $_;
99             }
100             }
101              
102             # Do the actual work
103 0           require feature;
104 0 0         feature->import(@on) if @on;
105 0 0         feature->unimport(@off) if @off;
106             }
107              
108             # Note that attribute syntax, i.e. :Export(-?), was not working before version 0.11 of .
109             # So we take the more verbose approach, as below:
110             __PACKAGE__->exporter_register_option('features', \&features, '?');
111              
112             1;
113              
114             __END__