File Coverage

blib/lib/Sub/Exporter/GlobExporter.pm
Criterion Covered Total %
statement 35 36 97.2
branch 9 10 90.0
condition 2 3 66.6
subroutine 9 9 100.0
pod 0 1 0.0
total 55 59 93.2


line stmt bran cond sub pod time code
1 1     1   69181 use strict;
  1         15  
  1         27  
2 1     1   6 use warnings;
  1         2  
  1         52  
3             package Sub::Exporter::GlobExporter 0.006;
4             # ABSTRACT: export shared globs with Sub::Exporter collectors
5              
6 1     1   7 use Scalar::Util ();
  1         2  
  1         23  
7              
8 1     1   658 use Sub::Exporter -setup => [ qw(glob_exporter) ];
  1         13893  
  1         8  
9              
10             #pod =head1 SYNOPSIS
11             #pod
12             #pod First, you write something that exports globs:
13             #pod
14             #pod package Shared::Symbol;
15             #pod
16             #pod use Sub::Exporter;
17             #pod use Sub::Exporter::GlobExport qw(glob_exporter);
18             #pod
19             #pod use Sub::Exporter -setup => {
20             #pod ...
21             #pod collectors => { '$Symbol' => glob_exporter(Symbol => \'_shared_globref') },
22             #pod };
23             #pod
24             #pod sub _shared_globref { return \*Common }
25             #pod
26             #pod Now other code can import C<$Symbol> and get their C<*Symbol> made an alias to
27             #pod C<*Shared::Symbol::Common>.
28             #pod
29             #pod If you don't know what this means or why you'd want to do it, you may want to
30             #pod stop reading now.
31             #pod
32             #pod The other class can do something like this:
33             #pod
34             #pod use Shared::Symbol '$Symbol';
35             #pod
36             #pod print $Symbol; # prints the scalar entry of *Shared::Symbol::Common
37             #pod
38             #pod ...or...
39             #pod
40             #pod use Shared::Symbol '$Symbol' => { -as => 'SharedSymbol' };
41             #pod
42             #pod print $SharedSymbol; # prints the scalar entry of *Shared::Symbol::Common
43             #pod
44             #pod ...or...
45             #pod
46             #pod my $glob;
47             #pod use Shared::Symbol '$Symbol' => { -as => \$glob };
48             #pod
49             #pod print $$glob; # prints the scalar entry of *Shared::Symbol::Common
50             #pod
51             #pod =head1 OVERVIEW
52             #pod
53             #pod Sub::Exporter::GlobExporter provides only one routine, C, which
54             #pod may be called either by its full name or may be imported on request.
55             #pod
56             #pod my $exporter = glob_exporter( $default_name, $globref_locator );
57             #pod
58             #pod The routine returns a L
59             #pod Configuration> that will export a glob into the importing package. It will
60             #pod export it under the name C<$default_name>, unless an alternate name is given
61             #pod (as shown above). The glob that is installed is specified by the
62             #pod C<$globref_locator>, which can be either the globref itself, or a reference to
63             #pod a string which will be called on the exporter
64             #pod
65             #pod For an example, see the L, in which a method is defined to produce
66             #pod the globref to share. This allows the glob-exporting package to be subclassed,
67             #pod so the subclass may choose to either re-use the same glob when exporting or to
68             #pod export a new one.
69             #pod
70             #pod If there are entries in the arguments to the globref-exporting collector
71             #pod I than those beginning with a dash, a hashref of them will be passed to
72             #pod the globref locator. In other words, if we were to write this:
73             #pod
74             #pod use Shared::Symbol '$Symbol' => { arg => 1, -as => 2 };
75             #pod
76             #pod It would result in a call like the following:
77             #pod
78             #pod my $globref = Shared::Symbol->_shared_globref({ arg => 1 });
79             #pod
80             #pod =cut
81              
82             my $is_ref;
83             BEGIN {
84             $is_ref = sub {
85             return(
86 3   66     25 ! Scalar::Util::blessed($_[0])
87             && Scalar::Util::reftype($_[0]) eq $_[1]
88             );
89 1     1   636 };
90             }
91              
92             sub glob_exporter {
93 2     2 0 282 my ($default_name, $globref) = @_;
94              
95 3     3   6 my $globref_method = $is_ref->($globref, 'GLOB') ? sub { $globref }
96 2 50       5 : $is_ref->($globref, 'SCALAR') ? $$globref
    100          
97             : Carp::confess("illegal glob locator '$globref'");
98              
99             return sub {
100 3     3   1093 my ($value, $data) = @_;
101              
102             my @args = defined $value
103 3 100       13 ? ({ map {; $_ => $value->{$_} } grep { ! /^-/ } keys %$value })
  0         0  
  2         11  
104             : ();
105              
106 3         10 my $globref = $data->{class}->$globref_method(@args);
107              
108 3         5 my $name;
109 3 100       7 $name = defined $value->{'-as'} ? $value->{'-as'} : $default_name;
110              
111 3 100       8 if (ref $name) {
112 1         3 $$name = *$globref;
113             } else {
114 2         5 my $sym = "$data->{into}::$name";
115              
116             {
117 1     1   10 no strict 'refs';
  1         2  
  1         123  
  2         5  
118 2         3 *{$sym} = *$globref;
  2         10  
119             }
120             }
121              
122             # Why is this line here? I have no recollection of it. -- rjbs, 2015-11-04
123 3         7 $_[0] = $globref;
124              
125 3         8 return 1;
126             }
127 2         14 }
128              
129             1;
130              
131             __END__