1 package Moose::Exporter;
7 use namespace::clean 0.08 ();
8 use List::MoreUtils qw( uniq );
14 sub build_import_methods {
18 my $exporting_package = caller();
20 $EXPORT_SPEC{$exporting_package} = \%args;
22 my @exports_from = $class->_follow_also( $exporting_package );
25 = $class->_process_exports( $exporting_package, @exports_from );
27 my $exporter = Sub::Exporter::build_exporter(
30 groups => { default => [':all'] }
34 my $import = $class->_make_import_sub(
36 $args{init_meta_args},
39 my $unimport = $class->_make_unimport_sub( [ keys %{$exports} ] );
42 *{ $exporting_package . '::import' } = $import;
43 *{ $exporting_package . '::unimport' } = $unimport;
51 my $exporting_package = shift;
53 %seen = ( $exporting_package => 1 );
55 return uniq( _follow_also_real($exporting_package) );
58 sub _follow_also_real {
59 my $exporting_package = shift;
61 die "Package in also ($exporting_package) does not seem to use MooseX::Exporter"
62 unless exists $EXPORT_SPEC{$exporting_package};
64 my $also = $EXPORT_SPEC{$exporting_package}{also};
66 return unless defined $also;
68 my @also = ref $also ? @{$also} : $also;
70 for my $package (@also)
72 die "Circular reference in also parameter to MooseX::Exporter between $exporting_package and $package"
78 return @also, map { _follow_also_real($_) } @also;
82 sub _process_exports {
88 for my $package (@packages) {
89 my $args = $EXPORT_SPEC{$package}
90 or die "The $package package does not use Moose::Exporter\n";
92 for my $name ( @{ $args->{with_caller} } ) {
95 \&{ $package . '::' . $name };
98 $exports{$name} = $class->_make_wrapped_sub(
105 for my $name ( @{ $args->{as_is} } ) {
110 $name = ( Class::MOP::get_code_info($name) )[1];
115 \&{ $package . '::' . $name };
119 $exports{$name} = sub {$sub};
127 # This variable gets closed over in each export _generator_. Then
128 # in the generator we grab the value and close over it _again_ in
129 # the real export, so it gets captured each time the generator
132 # In the meantime, we arrange for the import method we generate to
133 # set this variable to the caller each time it is called.
135 # This is all a bit confusing, but it works.
138 sub _make_wrapped_sub {
140 my $exporting_package = shift;
144 # We need to set the package at import time, so that when
145 # package Foo imports has(), we capture "Foo" as the
146 # package. This lets other packages call Foo::has() and get
147 # the right package. This is done for backwards compatibility
148 # with existing production code, not because this is a good
151 my $caller = $CALLER;
152 Class::MOP::subname( $exporting_package . '::'
153 . $name => sub { $sub->( $caller, @_ ) } );
157 sub _make_import_sub {
159 my $exporter = shift;
160 my $init_meta_args = shift;
164 # It's important to leave @_ as-is for the benefit of
168 $CALLER = Moose::Exporter::_get_caller(@_);
170 # this works because both pragmas set $^H (see perldoc
171 # perlvar) which affects the current compilation -
172 # i.e. the file who use'd us - which is why we don't need
173 # to do anything special to make it affect that file
174 # rather than this one (which is already compiled)
179 # we should never export to main
180 if ( $CALLER eq 'main' ) {
182 qq{$class does not export its sugar to the 'main' package.\n};
186 if ( $class->can('_init_meta') ) {
188 for_class => $CALLER,
189 %{ $init_meta_args || {} }
199 # 1 extra level because it's called by import so there's a layer
204 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
205 : ( ref $_[1] && defined $_[1]->{into_level} )
206 ? caller( $offset + $_[1]->{into_level} )
210 sub _make_unimport_sub {
212 my $exported = shift;
214 # [12:24] <mst> yes. that's horrible. I know. but it should work.
216 # This will hopefully be replaced in the future once
217 # namespace::clean has an API for it.
219 @_ = ( 'namespace::clean', @{$exported} );
221 goto &namespace::clean::import;
231 Moose::Exporter - make an import() and unimport() just like Moose.pm
235 package MyApp::Moose;
243 Moose::Exporter->build_export_methods(
244 export => [ 'sugar1', 'sugar2', \&Some::Random::thing ],
245 init_meta_args => { metaclass_class => 'MyApp::Meta::Class' ],
254 sugar1 'do your thing';
261 This module encapsulates the logic to export sugar functions like
262 C<Moose.pm>. It does this by building custom C<import> and C<unimport>
263 methods for your module, based on a spec your provide.
265 It also lets your "stack" Moose-alike modules so you can export
266 Moose's sugar as well as your own, along with sugar from any random
267 C<MooseX> module, as long as they all use C<Moose::Exporter>.
271 This module provides exactly one public method:
273 =head2 Moose::Exporter->build_import_methods(...)
275 When you call this method, C<Moose::Exporter> build custom C<import>
276 and C<unimport> methods for your module. The import method will export
277 the functions you specify, and you can also tell it to export
278 functions exported by some other module (like C<Moose.pm>).
280 The C<unimport> method cleans the callers namespace of all the
283 This method accepts the following parameters:
287 =item * with_caller => [ ... ]
289 This a list of function I<names only> to be exported wrapped and then
290 exported. The wrapper will pass the name of the calling package as the
291 first argument to the function. Many sugar functions need to know
292 their caller so they can get the calling package's metaclass object.
294 =item * as_is => [ ... ]
296 This a list of function names or sub references to be exported
297 as-is. You can identify a subroutine by reference, which is handy to
298 re-export some other module's functions directly by reference
299 (C<\&Some::Package::function>).
301 =item * init_meta_args
309 Dave Rolsky E<lt>autarch@urth.orgE<gt>
311 This is largely a reworking of code in Moose.pm originally written by
312 Stevan Little and others.
314 =head1 COPYRIGHT AND LICENSE
316 Copyright 2008 by Infinity Interactive, Inc.
318 L<http://www.iinteractive.com>
320 This library is free software; you can redistribute it and/or modify
321 it under the same terms as Perl itself.