File Coverage

blib/lib/Import/These.pm
Criterion Covered Total %
statement 67 70 95.7
branch 30 34 88.2
condition 6 8 75.0
subroutine 6 6 100.0
pod n/a
total 109 118 92.3


line stmt bran cond sub pod time code
1             package Import::These;
2              
3 11     11   775338 use strict;
  11         130  
  11         358  
4 11     11   64 use warnings;
  11         24  
  11         287  
5 11     11   53 use feature "say";
  11         19  
  11         2193  
6              
7              
8             our $VERSION = 'v0.1.0';
9              
10             # Marker is pushed to end of argument list to aid in processing.
11             # Make random to prevent collisions.
12             #
13             my $marker=join "", map int rand 26, 1..16;
14              
15              
16             sub import {
17 11     11   77 no strict "refs";
  11         31  
  11         7237  
18              
19 13     13   181 my $package=shift;
20              
21 13         25 my $prefix="";
22 13         67 my $k;
23             my $version;
24 13         0 my $mod;
25 13         0 my $prev_mod;
26 13         0 my $list;
27              
28 13         0 my $execute;
29              
30 13         34 push @_, $marker;
31            
32             # Save the target export level
33 13   50     129 my $target_level=($Exporter::ExportLevel||0)+1;
34              
35 13         22 my $i=0;
36 13         60 while(@_){
37 45         70 $k=shift;
38              
39             # Check if the next item is a ref, or a scalar
40             #
41 45         94 my $r=ref $k;
42 45 100       150 if($r eq "ARRAY"){
    50          
43 7         15 $list=$k;
44 7 100       21 $prev_mod=$mod if $mod; #version may have already shift this
45 7         10 $mod=undef;
46 7         14 $execute=1;
47             }
48             elsif($r eq ""){
49 38 100       219 if($k eq $marker){
    100          
    100          
    100          
    100          
50             # End processing if we hit the marker
51 12 100       33 $prev_mod=$mod if $mod;
52 12         24 $execute=!!$prev_mod;
53             }
54             elsif($k eq "::"){
55             # Exact. Clear prefix
56 1         2 $prefix="";
57 1         1 $prev_mod=$mod;
58 1         2 $mod=undef;
59             }
60             elsif($k =~ /^::.*?::$/){
61             # Double ended. Append new portion to prefix
62 2         7 $prefix.=substr $k, 2;
63 2         3 $prev_mod=$mod;
64 2         4 $mod=undef;
65             }
66             elsif($k =~/::$/){
67             # At end. Update prefix
68 7         13 $prefix=$k;
69 7         9 $prev_mod=$mod;
70 7         13 $mod=undef;
71             }
72             elsif($k =~ /^v|^\d/){
73             # Test if it looks like a version.
74 4 100       14 unless($i){
75             # Actually a perl version
76 1     1   61 eval "use $k";
  1         55  
  0            
77 1 50       1286 die $@ if $@;
78 0         0 next;
79             }
80             else {
81 3         7 $version=$k;
82 3         4 $prev_mod=$mod;
83 3         5 $mod=undef;
84             }
85             }
86             else {
87             # Module name
88 12         24 $prev_mod=$mod;
89 12         22 $mod=$k;
90 12         21 $execute=!!$prev_mod;
91             }
92             }
93             else {
94 0         0 die "Scalar or array ref only";
95             }
96              
97             # Attempt to execute/load what we have
98            
99            
100 44 100       100 if($execute){
101             #DEBUG
102 10 50       26 if($prev_mod){
103             #say "REQUIRE $prefix$prev_mod";
104             # Force export level to 0 so any imports of required package are
105             # relative to required package
106 10         21 local $Exporter::ExportLevel=0;
107 10         691 eval "require $prefix$prev_mod;";
108 10 50       3692 die "Could not require $prefix$prev_mod: $@" if $@;
109             }
110              
111             # After the package has been required, set the target level for import
112             #
113 10         24 local $Exporter::ExportLevel=$target_level;
114             #say "Target level is $Exporter::ExportLevel";
115              
116 10 100       29 if($version){
117             #say "IMPORTING $prefix$prev_mod with no import";
118 3         1257 "$prefix$prev_mod"->VERSION($version);
119             }
120              
121 9 100 100     84 if($list and @$list){
    100 66        
122             # List import
123             #say "IMPORTING $prefix$prev_mod with @$list";
124 6         207 "$prefix$prev_mod"->import(@$list);
125             }
126             elsif($list and @$list ==0){
127             # no not import
128             }
129             else {
130             # Default import
131             #say "IMPORTING $prefix$prev_mod with default";
132 2         55 "$prefix$prev_mod"->import();
133             }
134 9         24 $prev_mod=undef;
135 9         15 $list=undef;
136 9         17 $version=undef;
137             }
138 43         12706 $i++;
139             }
140             #say "END OF IMPORT::THESE IMPORT";
141             }
142              
143             __PACKAGE__;
144              
145             =head1 NAME
146              
147             Import::These - Terse, Prefixed and Multiple Imports with a Single Statement
148              
149             =head1 SYNOPSIS
150              
151             Any item ending with :: is a prefix. Any later items in the list will use the
152             prefix to create the full package name:
153              
154             #Instead of this:
155             #
156             use Plack::Middleware::Session;
157             use Plack::Middleware::Static;
158             use Plack::Middleware::Lint;
159             use IO::Compress::Gzip;
160             use IO::Compress::Gunzip;
161             use IO::Compress::Deflate;
162             use IO::Compress::Inflate;
163              
164              
165             # Do this
166             use Import::These qw<
167             Plack::Middleware:: Session Static Lint
168             IO::Compress:: Gzip GunZip Defalte Inflate
169             >;
170              
171              
172              
173             Any item exactly equal to :: clears the prefix:
174              
175             use Import::These "Prefix::", "Mod", "::", "Prefix::Another";
176             # Prefix::Mod
177             # Prefix::Another;
178              
179              
180             A item beginning with :: and ending with :: appends the item to the prefix:
181              
182             use Import::These "Plack::", "Test", "::Middleware::", "Lint";
183             # Plack::Test,
184             # Plack::Middleware::Lint;
185              
186              
187             Supports default, named/tagged, and no import:
188              
189             # Instead of this:
190             #
191             # use File::Spec::Functions;
192             # use File::Spec::Functions "catfile";
193             # use File::Spec::Functions ();
194              
195             # Do This:
196             #
197             use Import::These "File::Spec::", Functions,
198             Functions=>["catfile"],
199             Functions=>[]
200              
201             Supports Perl Version as first argument to list
202              
203             use Import::These qw;
204             # use v5.36;
205             # Plack::Test,
206             # Plack::Middleware::Lint;
207              
208             Supports Module Version
209              
210             use Import::These qw;
211             # use File::Spec::Functions 1.3;
212             #
213             use Import::These qw, ["catfile"];
214             # use File::Spec::Functions 1.3 "catfile";
215            
216             =head1 DESCRIPTION
217              
218             A tiny module for importing multiple modules in one statement utilising a
219             prefix. The prefix can be set, cleared, or appended multiple times in a list,
220             making long lists of imports much easier to type!
221              
222             It works with any package providing a C subroutine (i.e. compatible
223             with L. It also is compatible with recursive exporters such as
224             L manipulating the export levels.
225              
226              
227             =head1 USAGE
228              
229             When using this pragma, the list of arguments are interpreted as either a Perl
230             version, prefix mutation, module name, module version or array ref of symbols
231             to import. The current value of the prefix is applied to module names as they
232             appear in the list.
233              
234              
235             =over
236              
237             =item The prefix always starts out as an empty string.
238              
239             =item The first item in the list is optionally a Perl version
240              
241             =item Module version optionally comes after a module name (prefixed or not)
242              
243             =item Symbols list optionally comes after a module name or module version if used
244              
245             =item The prefix can be set/cleared/appended as many times as needed
246              
247             =back
248              
249             =head2 Prefix Manipulation
250              
251             The current prefix is used for all module names as they occur. However, changes
252             to the prefix can be interleaved within module names.
253              
254              
255             =head3 Set the Prefix
256              
257             Name::
258              
259             # Prefix equals "Name::"
260              
261             Any item in the list ending in "::" with result in the prefix being set to item (including the ::)
262              
263             =head3 Append The Prefix
264              
265             ::Name::
266              
267             # Prefix equals "OLDPREFIX::Name::"
268            
269             Any item in the list starting and ending with "::" will result in the prefix
270             having the item appended to it. The item has the leading "::" removed before
271             appending.
272              
273              
274             =head3 Clear the Prefix
275              
276             ::
277            
278             #Prefix is ""
279            
280             Any item in the list equal to "::" exactly will clear the prefix to an empty
281             string
282              
283             =head1 EXAMPLES
284              
285             The following examples make it easier to see the benefits of using this module:
286              
287             =head2 Simple Prefix
288              
289             A single prefix used for multiple packages:
290              
291             use Import::These qw;
292              
293             # Equivalent to:
294             # use IO::Compress::Gzip
295             # use IO::Compress::GunZip
296             # use IO::Compress::Deflate
297             # use IO::Compress::Inflate
298              
299             =head2 Appending Prefix
300              
301             Prefix is appended along the way:
302              
303             use Import::These qw;
304            
305             # Equivalent to:
306             # use IO::File
307             # use IO::Compress::Gzip
308             # use IO::Compress::GunZip
309             # use IO::Compress::Deflate
310             # use IO::Compress::Inflate
311              
312             =head2 Reset Prefix
313              
314             Completely change (reset) prefix to something else:
315              
316             use Import::These qw;
317              
318             # Equivalent to:
319             # use File::Spec::Functions
320             # use IO::Compress::Gzip
321             # use IO::Compress::GunZip
322             # use IO::Compress::Deflate
323             # use IO::Compress::Inflate
324              
325              
326             =head2 No Default Import
327              
328             use Import::These "File::Spec::", "Functions"=>[];
329              
330             # Equivalent to:
331             # use File::Spec::Functions ();
332            
333             =head2 Import Names/groups
334              
335             use Import::These "File::Spec::", "Functions"=>["catfile"];
336              
337             # Equivalent to:
338             # use File::Spec::Functions ("catfile");
339              
340              
341             =head2 With Perl Version
342              
343             use Import::These "v5.36", "File::Spec::", "Functions";
344              
345             # Equivalent to:
346             # use v5.36;
347             # use File::Spec::Functions;
348              
349             =head2 With Module Version
350              
351             use Import::These "File::Spec::", "Functions", "v1.2";
352              
353             # Equivalent to:
354             # use File::Spec::Functions v1.2;
355              
356              
357             =head2 All Together Now
358              
359             use Import::These qw, ["catfile"], qw<:: IO::Compress:: Gzip GunZip Deflate Inflate>;
360              
361             # Equivalent to:
362             # use v5.36;
363             # use File::IO;
364             # use File::Spec::Functions v1.2 "catfile"
365             # use IO::Compress::Gzip;
366             # use IO::Compress::GunZip;
367             # use IO::Compress::Deflate;
368             # use IO::Compress::Inflate;
369              
370              
371             =head1 COMPARISON TO OTHER MODULES
372              
373             L Performs can perform multiple imports, however requires a
374             custom package to group the imports and reexport them. Does not support
375             prefixes.
376              
377             L is very similar however does not support prefixes.
378              
379              
380             L works by loading ALL packages under a common prefix. Whether you need
381             them or not. That could be a lot of disk access and memory usage.
382              
383             L has automatic module installation using CPAN. However no
384             prefix support and uses B of RAM for basic importing
385              
386             L has some nice features but not a 'simple' package prefix. It also
387             looks like it only handles a single package per invocation
388              
389             =head1 REPOSITOTY and BUGS
390              
391             Please report and feature requests or bugs via the github repo:
392              
393             L
394              
395             =head1 AUTHOR
396              
397             Ruben Westerberg, Edrclaw@mac.comE
398              
399             =head1 COPYRIGHT AND LICENSE
400              
401             Copyright (C) 2023 by Ruben Westerberg
402              
403             Licensed under MIT
404              
405             =head1 DISCLAIMER OF WARRANTIES
406              
407             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
408             INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
409             FITNESS FOR A PARTICULAR PURPOSE.
410              
411             =cut
412            
413