File Coverage

blib/lib/Z.pm
Criterion Covered Total %
statement 57 82 69.5
branch 5 18 27.7
condition 2 10 20.0
subroutine 14 14 100.0
pod 0 3 0.0
total 78 127 61.4


line stmt bran cond sub pod time code
1 1     1   55685 use 5.008008;
  1         3  
2 1     1   5 use strict;
  1         1  
  1         19  
3 1     1   4 use warnings;
  1         2  
  1         42  
4              
5             package Z;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.008';
9              
10 1     1   393 use Import::Into ();
  1         2194  
  1         17  
11 1     1   435 use IO::Handle ();
  1         5275  
  1         24  
12 1     1   7 use Module::Runtime qw( use_module );
  1         1  
  1         6  
13 1     1   492 use Zydeco::Lite qw( true false );
  1         160620  
  1         7  
14              
15             BEGIN {
16 1 50   1   1704 *PERL_IS_MODERN = ( $] ge '5.014' ) ? \&true : \&false;
17             }
18              
19             my $STRICT = 0;
20             $ENV{$_} && ++$STRICT && last for qw(
21             EXTENDED_TESTING
22             AUTHOR_TESTING
23             RELEASE_TESTING
24             PERL_STRICT
25             );
26              
27             sub import {
28 1     1   10 my ( $target, $class ) = ( scalar caller, shift );
29            
30 1         1 my $mode = '-modern';
31 1 50 50     7 ( $_[0] || '' ) =~ /^-/ and $mode = shift;
32            
33 1         2 my $collection = 'modules';
34            
35 1         1 if ( PERL_IS_MODERN ) {
36 1 50       3 $collection = 'compat_modules' if $mode eq '-compat';
37             }
38             else {
39             $collection = 'compat_modules';
40            
41             if ( $mode eq '-modern' ) {
42             require Carp;
43             return Carp::croak( "$target requires Perl v5.14 or above; stopping" );
44             }
45             elsif ( $mode eq '-detect' ) {
46             require Carp;
47             Carp::carp(
48             "$target may require Perl v5.14 or above; attempting compatibility mode" );
49             }
50             } #/ else [ if ( PERL_IS_MODERN ) ]
51            
52 1         4 for my $modules ( $class->$collection ) {
53 12         134746 my ( $name, $version, @args ) = @$modules;
54 12         38 use_module( $name, $version )->import::into( $target, @args );
55             }
56            
57             eval {
58 1         413 require indirect;
59 1         852 'indirect'->unimport::out_of( $target );
60 1         181 1;
61             }
62             or !$STRICT
63 1 50 33     252 or do {
64 0         0 require Carp;
65 0         0 Carp::carp( "Could not load indirect.pm" );
66             };
67            
68 1         7 $class->also( $target, @_ );
69            
70 1         4 use_module( 'namespace::autoclean' )->import::into( $target );
71            
72 1         304 return $class;
73             } #/ sub import
74              
75             sub modules {
76 1     1 0 1 my $class = shift;
77            
78             return (
79 1         8 [ 'Syntax::Keyword::Try', '0.018', qw( try ) ],
80             [ 'Zydeco::Lite', '0.070', qw( -all ) ],
81             [ 'Types::Standard', '1.010000', qw( -types -is -assert ) ],
82             [ 'Types::Common::Numeric', '1.010000', qw( -types -is -assert ) ],
83             [ 'Types::Common::String', '1.010000', qw( -types -is -assert ) ],
84             [ 'Types::Path::Tiny', '0', qw( -types -is -assert ) ],
85             [ 'Object::Adhoc', '0.003', qw( object ) ],
86             [ 'Path::Tiny', '0.101', qw( path ) ],
87             [ 'match::simple', '0.010', qw( match ) ],
88             [ 'strict', '0', qw( refs subs vars ) ],
89             [ 'warnings', '0', qw( all ) ],
90             [ 'feature', '0', qw( say state ) ],
91             );
92             } #/ sub modules
93              
94             sub compat_modules {
95 1     1 0 1 my $class = shift;
96            
97             my @modules =
98 1         2 grep { my $name = $_->[0]; $name !~ /feature|Try/ } $class->modules;
  12         11  
  12         25  
99            
100 1         4 push @modules, [ 'Try::Tiny', '0.30' ];
101            
102 1 50       3 if ( $] ge '5.010' ) {
103 1         2 push @modules, [ 'feature', '0', qw( say ) ];
104             }
105             else {
106 0         0 push @modules, [ 'Perl6::Say', '0.06' ];
107 0         0 push @modules, [ 'UNIVERSAL::DOES', '0.001' ];
108             }
109            
110 1         3 return @modules;
111             } #/ sub compat_modules
112              
113             my %also = (
114             Dumper => sub {
115             require Data::Dumper;
116             return sub {
117             local $Data::Dumper::Deparse;
118             Data::Dumper::Dumper( @_ );
119             };
120             },
121             croak => sub {
122             return sub {
123             require Carp;
124             Carp::croak( @_ > 1 ? sprintf( shift, @_ ) : @_ );
125             };
126             },
127             carp => sub {
128             return sub {
129             require Carp;
130             Carp::carp( @_ > 1 ? sprintf( shift, @_ ) : @_ );
131             };
132             },
133             cluck => sub {
134             return sub {
135             require Carp;
136             Carp::cluck( @_ > 1 ? sprintf( shift, @_ ) : @_ );
137             };
138             },
139             maybe => sub {
140             if ( eval 'use PerlX::Maybe::XS 0.003 (); 1' ) {
141             return \&PerlX::Maybe::XS::maybe;
142             }
143             return sub ($$@) {
144             ( defined $_[0] and defined $_[1] )
145             ? @_
146             : ( ( @_ > 1 ) ? @_[ 2 .. $#_ ] : qw() );
147             };
148             },
149             provided => sub {
150             if ( eval 'use PerlX::Maybe::XS 0.003 (); 1' ) {
151             return \&PerlX::Maybe::XS::provided;
152             }
153             return sub ($$$@) {
154             ( shift )
155             ? @_
156             : ( ( @_ > 1 ) ? @_[ 2 .. $#_ ] : qw() );
157             };
158             },
159             encode_json => sub {
160             if ( eval 'use JSON::MaybeXS 1.003000 (); 1' ) {
161             return \&JSON::MaybeXS::encode_json;
162             }
163             require JSON::PP;
164             return \&JSON::PP::encode_json;
165             },
166             decode_json => sub {
167             if ( eval 'use JSON::MaybeXS 1.003000 (); 1' ) {
168             return \&JSON::MaybeXS::decode_json;
169             }
170             require JSON::PP;
171             return \&JSON::PP::decode_json;
172             },
173             STRICT => sub {
174             $STRICT ? sub () { !!1 } : sub () { !!0 };
175             },
176             LAX => sub {
177             $STRICT ? sub () { !!0 } : sub () { !!1 };
178             },
179             all => q(List::Util),
180             any => q(List::Util),
181             first => q(List::Util),
182             head => q(List::Util),
183             max => q(List::Util),
184             maxstr => q(List::Util),
185             min => q(List::Util),
186             minstr => q(List::Util),
187             none => q(List::Util),
188             notall => q(List::Util),
189             pairfirst => q(List::Util),
190             pairgrep => q(List::Util),
191             pairkeys => q(List::Util),
192             pairmap => q(List::Util),
193             pairs => q(List::Util),
194             pairvalues => q(List::Util),
195             product => q(List::Util),
196             reduce => q(List::Util),
197             reductions => q(List::Util),
198             sample => q(List::Util),
199             shuffle => q(List::Util),
200             sum => q(List::Util),
201             sum0 => q(List::Util),
202             tail => q(List::Util),
203             uniq => q(List::Util),
204             uniqnum => q(List::Util),
205             uniqstr => q(List::Util),
206             unpairs => q(List::Util),
207             blessed => q(Scalar::Util),
208             dualvar => q(Scalar::Util),
209             isdual => q(Scalar::Util),
210             isvstring => q(Scalar::Util),
211             isweak => q(Scalar::Util),
212             looks_like_number => q(Scalar::Util),
213             openhandle => q(Scalar::Util),
214             readonly => q(Scalar::Util),
215             refaddr => q(Scalar::Util),
216             reftype => q(Scalar::Util),
217             set_prototype => q(Scalar::Util),
218             tainted => q(Scalar::Util),
219             unweaken => q(Scalar::Util),
220             weaken => q(Scalar::Util),
221             prototype => q(Sub::Util),
222             set_prototype => q(Sub::Util),
223             set_subname => q(Sub::Util),
224             subname => q(Sub::Util),
225             check_module_name => q(Module::Runtime),
226             check_module_spec => q(Module::Runtime),
227             compose_module_name => q(Module::Runtime),
228             is_module_name => q(Module::Runtime),
229             is_module_spec => q(Module::Runtime),
230             is_valid_module_name => q(Module::Runtime),
231             is_valid_module_spec => q(Module::Runtime),
232             module_notional_filename => q(Module::Runtime),
233             require_module => q(Module::Runtime),
234             use_module => q(Module::Runtime),
235             use_package_optimistically => q(Module::Runtime),
236             );
237              
238             sub also {
239 1     1 0 4 my ( $class, $target ) = ( shift, shift );
240            
241 1         3 my %imports;
242 1         3 for my $arg ( @_ ) {
243 0         0 my ( $func, $dest ) = split /:/, $arg;
244 0 0       0 $dest = $func unless $dest;
245            
246 0 0       0 my $source = $also{$func} or do {
247 0         0 require Carp;
248 0         0 Carp::croak( "Do not know where to find function $func" );
249 0         0 next;
250             };
251            
252 0 0 0     0 push @{ $imports{ ref( $source ) or $source } ||= [] },
  0   0     0  
253             ref( $source ) ? [ $dest, $source ] : [ $dest, $func ];
254             } #/ for my $arg ( @_ )
255            
256 1         4 for my $source ( sort keys %imports ) {
257 0 0         if ( $source eq 'CODE' ) {
258 0           for my $func ( @{ $imports{$source} } ) {
  0            
259 0           my ( $name, $gen ) = @$func;
260 1     1   9 no strict 'refs';
  1         7  
  1         69  
261 0           *{"$target\::$name"} = $gen->();
  0            
262             }
263             }
264             else {
265 0           use_module( $source );
266 0           for my $func ( @{ $imports{$source} } ) {
  0            
267 0           my ( $name, $orig ) = @$func;
268 1     1   6 no strict 'refs';
  1         2  
  1         119  
269 0           *{"$target\::$name"} = \&{"$source\::$orig"};
  0            
  0            
270             }
271             }
272             } #/ for my $source ( sort keys...)
273             } #/ sub also
274              
275             1;
276              
277             __END__
278              
279             =pod
280              
281             =encoding utf-8
282              
283             =head1 NAME
284              
285             Z - collection of modules for rapid app development
286              
287             =head1 SYNOPSIS
288              
289             This:
290              
291             use Z;
292              
293             Is a shortcut for:
294              
295             use strict;
296             use warnings;
297             use feature 'say', 'state';
298             use namespace::autoclean;
299             use Syntax::Keyword::Try 'try';
300             use Zydeco::Lite -all;
301             use Path::Tiny 'path';
302             use Object::Adhoc 'object';
303             use match::simple 'match';
304             use Types::Standard -types, -is, -assert;
305             use Types::Common::String -types, -is, -assert;
306             use Types::Common::Numeric -types, -is, -assert;
307             use Types::Path::Tiny -types, -is, -assert;
308              
309             It will also do C<< no indirect >> if L<indirect> is installed.
310              
311             =head1 DESCRIPTION
312              
313             Just a shortcut for loading a bunch of modules that allow you to
314             quickly code Perl stuff. I've tried to avoid too many domain-specific
315             modules like HTTP::Tiny, etc. The modules chosen should be broadly
316             useful for a wide variety of tasks.
317              
318             =head2 Perl Version Compatibility
319              
320             By default, Z requires Perl v5.14, but it has a compatibility mode where
321             for Perl v5.8.8 and above.
322              
323             It will use L<Try::Tiny> instead of L<Syntax::Keyword::Try>. (Bear in mind
324             that these are not 100% compatible with each other.) It will also load
325             L<Perl6::Say> as a fallback for the C<say> built-in. And it will not provide
326             C<state>. It will also load L<UNIVERSAL::DOES> if there's no built-in
327             UNIVERSAL::DOES method.
328              
329             You can specify whether you want the modern modules or the compatibility
330             modules:
331              
332             use Z -modern;
333             # Uses modern modules.
334             # Requres Perl 5.14+.
335            
336             use Z -compat;
337             # Uses compatible modules.
338             # Requires Perl 5.8.8+.
339            
340             use Z -detect;
341             # Uses modern modules on Perl 5.14+.
342             # Prints a warning and uses compatible modules on Perl 5.8.8+.
343              
344             The default is C<< -modern >>.
345              
346             =head2 Additional Functions
347              
348             There are a whole bunch of other useful functions that Z I<could> make
349             available, but it's hard to know the best place to draw the line. So
350             other functions are available on request:
351              
352             use Z qw( weaken unweaken isweak );
353            
354             use Z -compat, qw( pairmap pairgrep );
355            
356             # Rename functions...
357             use Z qw( pairmap:pmap pairgrep:pgrep );
358              
359             (The things listed in the L</SYNOPSIS> are always imported and don't
360             support the renaming feature.)
361              
362             The additional functions available are: everything from L<Scalar::Util>,
363             everything from L<List::Util>, everything from L<Sub::Util>, everything
364             from L<Carp> (wrapped versions with C<sprintf> functionality, except
365             C<confess> which is part of the standard set of functions already),
366             all the functions (but not the exported regexps) from L<Module::Runtime>,
367             C<Dumper> from L<Data::Dumper>, C<maybe> and C<provided> from
368             L<PerlX::Maybe>, C<encode_json> and C<decode_json> from
369             L<JSON::MaybeXS> or L<JSON::PP> (depending which is installed), and
370             C<STRICT> and C<LAX> from L<Devel::StrictMode>.
371              
372             If you specify a compatibility mode (like C<< -modern >>), this must be
373             first in the import list.
374              
375             =head1 BUGS
376              
377             Please report any bugs to
378             L<http://rt.cpan.org/Dist/Display.html?Queue=Z>.
379              
380             =head1 SEE ALSO
381              
382             L<Zydeco::Lite>,
383             L<Types::Standard>,
384             L<Syntax::Feature::Try>,
385             L<Path::Tiny>,
386             L<match::simple>,
387             L<Object::Adhoc>.
388              
389             =head1 AUTHOR
390              
391             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
392              
393             =head1 COPYRIGHT AND LICENCE
394              
395             This software is copyright (c) 2020 by Toby Inkster.
396              
397             This is free software; you can redistribute it and/or modify it under
398             the same terms as the Perl 5 programming language system itself.
399              
400             =head1 DISCLAIMER OF WARRANTIES
401              
402             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
403             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
404             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.