File Coverage

blib/lib/Exporter/Handy.pm
Criterion Covered Total %
statement 33 75 44.0
branch 0 14 0.0
condition 0 7 0.0
subroutine 11 21 52.3
pod 6 6 100.0
total 50 123 40.6


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