line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package MooseX::Scaffold; |
2
|
|
|
|
|
|
|
|
3
|
9
|
|
|
9
|
|
1002811
|
use warnings; |
|
9
|
|
|
|
|
103
|
|
|
9
|
|
|
|
|
326
|
|
4
|
9
|
|
|
9
|
|
48
|
use strict; |
|
9
|
|
|
|
|
19
|
|
|
9
|
|
|
|
|
737
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 NAME |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
MooseX::Scaffold - Template metaprogramming with Moose |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 VERSION |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Version 0.05 |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=cut |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = '0.05'; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 SYNOPSIS |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
package MyScaffolder; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
use MooseX::Scaffold; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
MooseX::Scaffold->setup_scaffolding_import; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub SCAFFOLD { |
27
|
|
|
|
|
|
|
my $class = shift; my %given = @_; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
$class->has($given{kind} => is => 'ro', isa => 'Int', required => 1); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Using MooseX::ClassAttribute |
32
|
|
|
|
|
|
|
$class->class_has(kind => is => 'ro', isa => 'Str', default => $given{kind}); |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
package MyAppleClass; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
use Moose; |
38
|
|
|
|
|
|
|
use MooseX::ClassAttribute; |
39
|
|
|
|
|
|
|
use MyScaffolder kind => 'apple'; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
package MyBananaClass; |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
use Moose; |
44
|
|
|
|
|
|
|
use MooseX::ClassAttribute; |
45
|
|
|
|
|
|
|
use MyScaffolder kind => 'banana'; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# ... meanwhile, back at the Batcave ... |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
use MyAppleClass; |
50
|
|
|
|
|
|
|
use MyBananaClass; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
my $apple = MyAppleClass->new(apple => 1); |
53
|
|
|
|
|
|
|
my $banana = MyBananaClass->new(banana => 2); |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 DESCRIPTION |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
MooseX::Scaffold is a tool for creating or augmenting Moose classes on-the-fly. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
Scaffolding can be triggered when a C<use> is executed (any import arguments are passed |
60
|
|
|
|
|
|
|
to the scaffold subroutine) or you can explicitly call MooseX::Scaffold->scaffold with the scaffolding |
61
|
|
|
|
|
|
|
subroutine and the package name for the class. |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
Depending on what you're trying to do, MooseX::Scaffold can behave in three different ways (Assume My::Class is the class |
64
|
|
|
|
|
|
|
you're trying to create/augment): |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
load_and_scaffold (scaffold) - Attempt to require My::Class from My/Class.pm or do Moose::Meta::Class->create('My::Class') |
67
|
|
|
|
|
|
|
to make the package on-the-fly. Scaffold the result. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
load_or_scaffold (load) - Attempt to require My::Class from My/Class.pm and stop if that works. If no My/Class.pm is |
70
|
|
|
|
|
|
|
found in @INC, then make a Moose class on-the-fly and scaffold it. |
71
|
|
|
|
|
|
|
This option can be used to create a default class if one isn't found. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
scaffold_without_load - Don't attempt to require My::Class, just create it on-the-fly and scaffold it. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head1 METHODS |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->scaffold( ... ) |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
Scaffold a class by either loading it or creating it. You can pass through the following: |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
scaffolder |
82
|
|
|
|
|
|
|
scaffolding_package This should be either a subroutine (sub { ... }) or a package name. If a package name |
83
|
|
|
|
|
|
|
is given, then the package should contain a subroutine called SCAFFOLD |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
class |
86
|
|
|
|
|
|
|
class_package The package name of resulting class |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
load_or_scaffold Attempt to load $class_package first and do nothing successful. Otherwise create |
89
|
|
|
|
|
|
|
$class_package and scaffold it |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
scaffold_without_load Scaffold $class_package without attempting to load it first. Does not have |
92
|
|
|
|
|
|
|
any effect if $class_package has been loaded already |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
no_class_attribute Set this to 1 to disable applying the MooseX::ClassAttribute meta-role |
95
|
|
|
|
|
|
|
on class creation. This has no effect if the class is loaded (If you |
96
|
|
|
|
|
|
|
want class_has with a loaded class, make sure to 'use MooseX::ClassAttribute') |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->load_and_scaffold( ... ) |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
An alias for ->scaffold |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->load_or_scaffold( ... ) |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
An alias for ->scaffold with C<load_or_scaffold> set to 1 |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->load( ... ) |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
An alias for ->load_or_scaffold |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->scaffold_without_load( ... ) |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
An alias for ->scaffold with C<scaffold_without_load> set to 1 |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->build_scaffolding_import( ... ) |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Return an anonymous subroutine suitable for use an an import function |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Anything passable to ->scaffold is fair game. In addition: |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
scaffolder This will default to the package of caller() if unspecified |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
chain_import An (optional) subroutine that will goto'd after scaffolding is complete |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->setup_scaffolding_import( ... ) |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
Install an import subroutine. By default, caller() will be used for the exporting package, but |
127
|
|
|
|
|
|
|
another may be specified. |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Anything passable to ->build_scaffolding_import is fair game. In addition: |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
exporter |
132
|
|
|
|
|
|
|
exporting_package The package that will house the import subroutine (the scaffolding will trigger |
133
|
|
|
|
|
|
|
when the package is used or imported) |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=cut |
136
|
|
|
|
|
|
|
|
137
|
9
|
|
|
9
|
|
15172
|
use Class::Inspector; |
|
9
|
|
|
|
|
50417
|
|
|
9
|
|
|
|
|
339
|
|
138
|
9
|
|
|
9
|
|
8937
|
use Carp::Clan; |
|
9
|
|
|
|
|
20742
|
|
|
9
|
|
|
|
|
64
|
|
139
|
9
|
|
|
9
|
|
26072
|
use Moose(); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
no Moose; |
141
|
|
|
|
|
|
|
use Moose::Exporter; |
142
|
|
|
|
|
|
|
use MooseX::ClassAttribute(); |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
use MooseX::Scaffold::Class; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->load_package( $package ) |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=head2 MooseX::Scaffold->load_class( $class ) |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
A convenience method that will attempt to require $package or $class if not already loaded |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Essentially does ... |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
eval "require $package;" or die $@ |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
... but uses Class::Inspector to check for $package existence first (%INC is not trustworthy) |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=cut |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub load_package { |
161
|
|
|
|
|
|
|
my $self = shift; |
162
|
|
|
|
|
|
|
my $package = shift; |
163
|
|
|
|
|
|
|
return 1 if Class::Inspector->loaded($package); |
164
|
|
|
|
|
|
|
eval "require $package;" or die $@; |
165
|
|
|
|
|
|
|
return 1; # FIXME |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub load_class { |
169
|
|
|
|
|
|
|
return shift->load_package(@_); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub setup_scaffolding_import { |
173
|
|
|
|
|
|
|
my $self = shift; |
174
|
|
|
|
|
|
|
my %given = @_; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
my $exporting_package = $given{exporting_package}; |
177
|
|
|
|
|
|
|
$exporting_package ||= $given{exporter} ? delete $given{exporter} : scalar caller; |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
my $scaffolder = $given{scaffolder} ||= scalar caller; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
my ( $import, $unimport ) = $self->build_scaffolding_import( %given ); |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
eval "package $exporting_package;"; |
184
|
|
|
|
|
|
|
croak "Couldn't open exporting package $exporting_package since: $@" if $@; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
no strict 'refs'; |
187
|
|
|
|
|
|
|
*{ $exporting_package . '::import' } = $import; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub build_scaffolding_import { |
191
|
|
|
|
|
|
|
my $self = shift; |
192
|
|
|
|
|
|
|
my %given = @_; |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
my $scaffolder = $given{scaffolder} ||= scalar caller; |
195
|
|
|
|
|
|
|
my $chain_import = $given{chain_import}; |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
return sub { |
198
|
|
|
|
|
|
|
my $CALLER = Moose::Exporter::_get_caller(@_); |
199
|
|
|
|
|
|
|
my $exporting_package = shift; |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
return if $CALLER eq 'main'; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# TODO Check to see if $CALLER is a Moose::Object? |
204
|
|
|
|
|
|
|
$self->scaffold( |
205
|
|
|
|
|
|
|
class_package => $CALLER, |
206
|
|
|
|
|
|
|
exporting_package => $exporting_package, |
207
|
|
|
|
|
|
|
%given, \@_ |
208
|
|
|
|
|
|
|
); |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
goto &$chain_import if $chain_import; |
211
|
|
|
|
|
|
|
}; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub load { |
215
|
|
|
|
|
|
|
my $self = shift; |
216
|
|
|
|
|
|
|
return $self->scaffold(@_, load_or_scaffold => 1); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub load_or_scaffold { |
220
|
|
|
|
|
|
|
my $self = shift; |
221
|
|
|
|
|
|
|
return $self->load(@_); |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub load_and_scaffold { |
225
|
|
|
|
|
|
|
my $self = shift; |
226
|
|
|
|
|
|
|
return $self->scaffold(@_); |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub scaffold_without_load { |
230
|
|
|
|
|
|
|
my $self = shift; |
231
|
|
|
|
|
|
|
return $self->scaffold(@_, scaffold_without_load => 1); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
sub scaffold { |
235
|
|
|
|
|
|
|
my $self = shift; |
236
|
|
|
|
|
|
|
my $arguments = []; |
237
|
|
|
|
|
|
|
$arguments = pop @_ if ref $_[-1] eq 'ARRAY'; |
238
|
|
|
|
|
|
|
my %given = @_; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
my $class_package = $given{class_package} || $given{class}; |
241
|
|
|
|
|
|
|
my $scaffolder = $given{scaffolding_package} || $given{scaffolder}; |
242
|
|
|
|
|
|
|
my $load_or_scaffold = $given{load_or_scaffold}; |
243
|
|
|
|
|
|
|
my $scaffold_without_load = $given{scaffold_without_load}; |
244
|
|
|
|
|
|
|
my $no_class_attribute = $given{no_class_attribute}; |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
if (Class::Inspector->loaded($class_package)) { |
247
|
|
|
|
|
|
|
return if ! $scaffold_without_load && $load_or_scaffold; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
else { |
250
|
|
|
|
|
|
|
if (! $scaffold_without_load && Class::Inspector->installed($class_package)) { |
251
|
|
|
|
|
|
|
eval "require $class_package;"; |
252
|
|
|
|
|
|
|
die $@ if $@; |
253
|
|
|
|
|
|
|
return if $load_or_scaffold; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
else { |
256
|
|
|
|
|
|
|
my $meta = Moose::Meta::Class->create($class_package); |
257
|
|
|
|
|
|
|
unless ($no_class_attribute) { |
258
|
|
|
|
|
|
|
MooseX::ClassAttribute->init_meta( for_class => $class_package ); |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
my $scaffolding_package; |
264
|
|
|
|
|
|
|
if (ref $scaffolder eq 'CODE') { |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
else { |
267
|
|
|
|
|
|
|
$scaffolding_package = $scaffolder; |
268
|
|
|
|
|
|
|
$self->_load_scaffolding_package( $scaffolding_package ); |
269
|
|
|
|
|
|
|
$scaffolder = $scaffolding_package->can('SCAFFOLD'); |
270
|
|
|
|
|
|
|
croak "Unable to find method SCAFFOLD in package $scaffolding_package" unless $scaffolder; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
$self->_scaffold( $class_package, $scaffolder, @$arguments, scaffolding_package => $scaffolding_package ); |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub _load_scaffolding_package { |
278
|
|
|
|
|
|
|
my $self = shift; |
279
|
|
|
|
|
|
|
my $scaffolding_package = shift; |
280
|
|
|
|
|
|
|
return if Class::Inspector->loaded($scaffolding_package); |
281
|
|
|
|
|
|
|
eval "require $scaffolding_package;" or croak "Unable to load scaffolding class $scaffolding_package since: $@"; |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub _scaffold { |
285
|
|
|
|
|
|
|
my $self = shift; |
286
|
|
|
|
|
|
|
my $class_package = shift; |
287
|
|
|
|
|
|
|
my $scaffolder = shift; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
my $class = MooseX::Scaffold::Class->new($class_package); |
290
|
|
|
|
|
|
|
$scaffolder->($class, @_, class_package => $class_package); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub parent_package { |
294
|
|
|
|
|
|
|
my $self = shift; |
295
|
|
|
|
|
|
|
my $package = shift; |
296
|
|
|
|
|
|
|
return $self->repackage($package, undef, shift); |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub child_package { |
300
|
|
|
|
|
|
|
my $self = shift; |
301
|
|
|
|
|
|
|
my $package = shift; |
302
|
|
|
|
|
|
|
return $self->repackage($package, shift); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub repackage { |
306
|
|
|
|
|
|
|
my $self = shift; |
307
|
|
|
|
|
|
|
my $package = shift; |
308
|
|
|
|
|
|
|
my $replacement = shift; |
309
|
|
|
|
|
|
|
my $count = shift; |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
$count = 0 unless defined $count && length $count; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
return $package unless $count >= 1; |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
my @package = split m/::/, $package; |
316
|
|
|
|
|
|
|
pop @package while $count--; |
317
|
|
|
|
|
|
|
push @package, $replacement if defined $replacement && length $replacement; |
318
|
|
|
|
|
|
|
return join '::', @package; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=head1 AUTHOR |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
Robert Krimen, C<< <rkrimen at cpan.org> >> |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=head1 SOURCE |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
You can contribute or fork this project via GitHub: |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
L<http://github.com/robertkrimen/moosex-scaffold/tree/master> |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
git clone git://github.com/robertkrimen/moosex-scaffold.git MooseX-Scaffold |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head1 BUGS |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
Please report any bugs or feature requests to C<bug-moosex-classscaffold at rt.cpan.org>, or through |
336
|
|
|
|
|
|
|
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=MooseX-Scaffold>. I will be notified, and then you'll |
337
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=head1 SUPPORT |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
perldoc MooseX::Scaffold |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
You can also look for information at: |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=over 4 |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=MooseX-Scaffold> |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
L<http://annocpan.org/dist/MooseX-Scaffold> |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
=item * CPAN Ratings |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
L<http://cpanratings.perl.org/d/MooseX-Scaffold> |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=item * Search CPAN |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
L<http://search.cpan.org/dist/MooseX-Scaffold> |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=back |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Copyright 2008 Robert Krimen, all rights reserved. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
380
|
|
|
|
|
|
|
under the same terms as Perl itself. |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=cut |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
1; # End of MooseX::Scaffold |