File Coverage

blib/lib/use/perl5.pm
Criterion Covered Total %
statement 38 78 48.7
branch 7 38 18.4
condition 3 12 25.0
subroutine 10 14 71.4
pod 0 4 0.0
total 58 146 39.7


line stmt bran cond sub pod time code
1             ##
2             # name: perl5
3             # abstract: Use a Perl 5 group of modules/features
4             # author: Ingy döt Net
5             # license: perl
6             # copyright: 2011
7             # see:
8             # - perl5i
9             # - perl5::i
10             # - perl5::ingy
11              
12             # To do:
13             # - Turn die to croak (with tests)
14              
15 1     1   13 use 5.008;
  1         3  
  1         33  
16             package use::perl5;
17 1     1   5 use strict;
  1         1  
  1         22  
18 1     1   5 use warnings;
  1         1  
  1         21  
19              
20 1     1   893 use version 0.77 ();
  1         2245  
  1         30  
21 1     1   925 use Hook::LexWrap 0.24;
  1         4690  
  1         7  
22              
23             our $VERSION = '0.08';
24              
25             my $requested_perl_version = 0;
26             my $perl_version = 10;
27              
28             sub VERSION {
29 0     0 0 0 my ($class, $version) = @_;
30 0         0 $version = version->parse($version);
31 0 0       0 if ($version < 10) {
32 0         0 my $this_version = do {
33 1     1   105 no strict 'refs';
  1         2  
  1         698  
34 0         0 version->parse(${$class . '::VERSION'});
  0         0  
35             };
36 0 0       0 if ($version > $this_version) {
37 0         0 require Carp;
38 0         0 Carp::croak(
39             "$class version $version required" .
40             "--this is only version $this_version"
41             );
42             }
43             }
44             else {
45 0         0 $requested_perl_version = $version;
46             }
47             }
48              
49             sub version_check {
50 0     0 0 0 my ($class, $args) = @_;
51              
52 0 0       0 if (defined $args->[0]) {
53 0         0 my $version = $args->[0];
54 0         0 $version =~ s/^-//;
55 0 0 0     0 if (version::is_lax($version) and version->parse($version) >= 10) {
56 0         0 $requested_perl_version = version->parse($version);
57 0         0 shift(@$args);
58             }
59             }
60 0 0       0 if ($requested_perl_version) {
61 0         0 my $version = $requested_perl_version->numify / 1000 + 5;
62 0         0 $perl_version = $requested_perl_version;
63 0         0 $requested_perl_version = 0;
64 0         0 eval "use $version";
65 0 0       0 do { require Carp; Carp::croak($@) } if $@;
  0         0  
  0         0  
66             }
67             }
68              
69             sub import {
70 0 0   0   0 return unless @_; # XXX not sure why
71 0         0 my $class = shift;
72 0         0 $class->version_check(\@_);
73 0         0 my $arg = shift;
74              
75 0 0       0 if ($class ne 'perl5') {
76 0         0 (my $usage = $class) =~ s/::/-/;
77 0         0 die "Don't 'use $class'. Try 'use $usage'";
78             }
79 0 0       0 die "Too many arguments for 'use perl5...'" if @_;
80              
81 0 0       0 my $subclass =
    0          
82             not(defined($arg)) ? __PACKAGE__ :
83             $arg =~ /^-(\w+)$/ ?__PACKAGE__ . "::$1" :
84             die "'$arg' is an invalid first argument to 'use perl5...'";
85 0 0       0 eval "require $subclass; 1" or die $@;
86              
87 0         0 @_ = ($subclass);
88 0         0 goto &{$class->can('importer')};
  0         0  
89             }
90              
91             sub importer {
92 1     1 0 2 my $class = shift;
93 1 50       4 my @imports = scalar(@_) ? @_ : $class->imports;
94 1         2 my @wrappers;
95              
96 1     1   2 my $important = sub {};
  1         13  
97              
98 1         4 while (@imports) {
99 1         1 my $name = shift(@imports);
100 1 50 33     5 my $version = (@imports and version::is_lax($imports[0]))
101             ? version->parse(shift(@imports))->numify : '';
102 1 50 33     20 my $arguments = (@imports and ref($imports[0]) eq 'ARRAY')
103             ? shift(@imports) : undef;
104              
105             $important = wrap $important => post => sub {
106 1 50   1   1259 eval "use $name $version (); 1" or die $@;
  1     1   17667  
  1         9  
  1         81  
107 1 50 33     10 return if $arguments and not @$arguments;
108 1 50       16 my $importee = $name->can('import') or return;
109 1 50       1 @_ = ($name, @{$arguments || []});
  1         10  
110 1         6 goto &$importee;
111 1         7 };
112             }
113              
114 1         28 goto &$important;
115             }
116              
117             sub imports {
118 0     0 0   my $subversion = int($perl_version);
119             return (
120 0           'strict',
121             'warnings',
122             'feature' => [":5.$subversion"],
123             );
124             }
125              
126             1;
127              
128             =head1 SYNOPSIS
129              
130             Use a version of Perl and its feature set:
131              
132             use perl5; # Same as 'use perl5 v5.10.0;'
133             use perl5 v14.1;
134             use perl5 14.1;
135             use perl5-14.1;
136              
137             Use a bundled feature set from a C plugin:
138              
139             use perl5-i;
140             use perl5-2i;
141             use perl5-modern;
142             use perl5-yourShinyPlugin;
143              
144             Or both:
145              
146             use perl5 v14.1 -shiny;
147              
148             =head1 DESCRIPTION
149              
150             The C module lets you C a well known set of modules in one
151             command.
152              
153             It allows people to create plugins like C and C that
154             are sets of useful modules that have been tested together and are known to
155             create joy.
156              
157             This module, C, is generally the base class to such a plugin.
158              
159             =head1 USAGE
160              
161             This:
162              
163             use perl5-foo;
164              
165             Is equivalent in Perl to:
166              
167             use perl5 '-foo';
168              
169             The C module takes the first argument in the C command, and uses
170             it to find a plugin, like C in this case.
171              
172             C is typically just a subclass of L. It invokes a set of
173             modules for its caller.
174              
175             If you use it with a version, like this:
176              
177             use perl5 v14;
178              
179             It is the same as saying:
180              
181             use v5.14;
182             use strict;
183             use warnings;
184             use feature ':5.14';
185              
186             If you use C with no arguments, like this:
187              
188             use perl5;
189              
190             It is the same as saying:
191              
192             use perl5 v10;
193              
194             =head1 PLUGIN API
195              
196             This module uses lexically-wrapped-goto-chaining-magic to correctly load a set
197             of modules (including optional version requirements and import options) into
198             the user's code. The API for specifying a perl5 plugin is very simple.
199              
200             To create a plugin called C that gets called like this:
201              
202             use perl5-foo;
203              
204             Write some code like this:
205              
206             package perl5::foo;
207             use base 'perl5';
208             our $VERSION = 0.12;
209              
210             # These is the list of modules (with optional version and arguments)
211             sub imports {
212             return (
213             strict =>
214             warnings =>
215             features => [':5.10'],
216             SomeModule => 0.22,
217             OtherModule => 0.33, [option1 => 2],
218             Module => [], # Don't invoke Module's import() method
219             );
220             }
221              
222             1;
223              
224             =head1 INSPIRATION
225              
226             This module was inspired by Michael Schwern's L, and the talk he gave
227             about it at the 2010 OSDC in Melbourne. By "inspired" I mean that I was
228             perturbed by Schwern's non-TMTOWTDI attitude towards choosing a standard set
229             of Perl modules for all of us.
230              
231             THIS IS PERL! THERE ARE NO STANDARDS!
232              
233             ...and I told him so. I also promised that I would show him my feelings in
234             code. Schwern, I is how I feel! (See also: L)
235              
236             =head1 THANKS
237              
238             Special thanks to schwern, mstrout, audreyt, rodrigo and jesse for ideas and
239             support.