File Coverage

blib/lib/Package/Tent.pm
Criterion Covered Total %
statement 53 54 98.1
branch 20 28 71.4
condition 4 8 50.0
subroutine 6 6 100.0
pod n/a
total 83 96 86.4


line stmt bran cond sub pod time code
1             package Package::Tent;
2             $VERSION = eval{require version}?version::qv($_):$_ for(0.0.1);
3              
4 2     2   55205 use warnings;
  2         4  
  2         65  
5 2     2   11 use strict;
  2         3  
  2         70  
6 2     2   11 use Carp;
  2         7  
  2         876  
7              
8             =head1 NAME
9              
10             Package::Tent - temporary package infrastructure
11              
12             =head1 SYNOPSIS
13              
14             This module allows you to setup camp inside an existing module/program
15             with minimal commitment to filenames, while still being able to use the
16             same require/use statements of normal code.
17              
18             use Package::Tent sub {
19             package Who::sYourDaddy;
20             sub thing {
21             print "hello world\n";
22             }
23             1;
24             };
25             use Package::Tent sub {
26             package What::sInAName;
27             use base 'Who::sYourDaddy';
28             sub method {
29             $_[0]->thing;
30             }
31             __PACKAGE__;
32             };
33              
34             use What::sInAName;
35             What::sInAName->method;
36              
37             =head1 USAGE
38              
39             The 'use Package::Tent sub {...}' statement is equivalent to wrapping
40             your package in a BEGIN block and setting an entry in %INC.
41              
42             Note that the first example simply returns a true value, while the
43             second explicitly returns the package name using the __PACKAGE__ token.
44             You may use either method.
45              
46             The implicit form will cause Package::Tent to attempt opening and
47             scanning the file containing the calling code. The latter is more
48             robust in strange (PAR, @INC hooks, etc.) environments, but is less
49             convenient.
50              
51             =head1 NOTES
52              
53             It is not wise to install a datacenter in a tent. Need I say more?
54              
55             This module was designed to reduce development time by allowing me to
56             maintain my train of thought. The scenario is that you're coding along
57             in some module or program and you realize the need for a support module
58             (or even a few of them.) Package::Tent allows you to keep writing code
59             while you're thinking rather than stopping long enough to commit to a
60             name, create a file, maybe add it to version control, etc.
61              
62             It should be similarly useful in single-file prototypes or other
63             experimental code. Hopefully, lowering the file-juggling overhead
64             encourages you to start your code with a modular style. When the
65             prototype becomes the finished product (as it so often does), the
66             refactoring is nearly mechanical as opposed to a difficult untangling of
67             ad-hoc variables.
68              
69             =cut
70              
71             =head1 Methods
72              
73             =head2 import
74              
75             use Package::Tent sub {
76             ...
77             };
78              
79             Package::Tent->import($subref);
80              
81             =cut
82              
83             sub import {
84 12     12   15627 my $self = shift;
85 12 100       55 @_ or return;
86 11         16 my ($subref) = @_;
87              
88 11 50 50     46 ((ref($subref) || '') eq 'CODE') or croak("must be a subref");
89              
90 11         34 my ($p, $fn, $line) = caller;
91              
92 11         16 my $v = eval {$subref->()};
  11         26  
93 11 50       45 $@ and die;
94 11 50       23 $v or croak("$subref did not return a true value");
95              
96 11 100       37 unless($v =~ m/^[a-z][a-z0-9:_]*$/i) {
97 9         11 $v = eval {$self->_find_package($fn, $line)};
  9         26  
98 9 50       21 if($@) {
99 0         0 croak($@, "\n\n -- you should use the __PACKAGE__ tag\n\n ");
100             }
101 9 50       23 $v or croak("failed to determine package name");
102             }
103              
104 11         20 my $pf = $v . '.pm';
105 11         32 $pf =~ s#::#/#g;
106 11         366 $INC{$pf} = $fn;
107             } # end subroutine import definition
108             ########################################################################
109              
110             =head2 _find_package
111              
112             Package::Tent->_find_package($file, $line);
113              
114             =cut
115              
116             sub _find_package {
117 9     9   13 my $self = shift;
118 9         13 my ($file, $num) = @_;
119 9 50       356 open(my $fh, '<', $file) or die("cannot open $file");
120              
121 9   33     44 my $pname = ref($self) || $self;
122              
123 2     2   10 use constant DBG => 0;
  2         4  
  2         976  
124              
125 9         10 DBG and warn "XX pname is $pname\n";
126              
127 9         14 my $ln = 0;
128 9         12 my $in_use = 0;
129 9         8 my $got_pack;
130 9         153 while(my $line = <$fh>) {
131 45         42 $ln++;
132 45         38 DBG and warn "## $line";
133 45 100 66     353 if($line =~ m/^\s*use \Q$pname\E *\(? *sub *\{(.*)/) {
    100          
134 14 100       71 if(my $also = $1) {
135 6 50       31 if($also =~ m/\bpackage ([\w:]+)/) {
136 6         16 $got_pack = $1;
137             }
138             }
139             else {
140 8         10 $got_pack = undef;
141             }
142 14         13 DBG and warn "XX in_use\n";
143 14         19 $in_use = 1;
144             }
145             elsif($in_use and ! defined($got_pack)) {
146 8         7 DBG and warn "XX check\n";
147 8 50       32 if($line =~ m/(?:^|;)\s*package ([\w:]+)/) {
148 8         13 $got_pack = $1;
149 8         10 DBG and warn "%% got $got_pack\n";
150             }
151             }
152 45 100       154 ($ln >= $num) and last;
153             }
154              
155 9         149 return($got_pack);
156             } # end subroutine _find_package definition
157             ########################################################################
158              
159             =head1 AUTHOR
160              
161             Eric Wilhelm @
162              
163             http://scratchcomputing.com/
164              
165             =head1 BUGS
166              
167             If you found this module on CPAN, please report any bugs or feature
168             requests through the web interface at L. I will be
169             notified, and then you'll automatically be notified of progress on your
170             bug as I make changes.
171              
172             If you pulled this development version from my /svn/, please contact me
173             directly.
174              
175             =head1 COPYRIGHT
176              
177             Copyright (C) 2007 Eric L. Wilhelm, All Rights Reserved.
178              
179             =head1 NO WARRANTY
180              
181             Absolutely, positively NO WARRANTY, neither express or implied, is
182             offered with this software. You use this software at your own risk. In
183             case of loss, no person or entity owes you anything whatsoever. You
184             have been warned.
185              
186             =head1 LICENSE
187              
188             This program is free software; you can redistribute it and/or modify it
189             under the same terms as Perl itself.
190              
191             =cut
192              
193             # vi:ts=2:sw=2:et:sta
194             1;