Revert the change to get rid of caller()-currying for Moose.pm
[gitmo/Moose.git] / lib / Moose / Exporter.pm
CommitLineData
5bd4db9b 1package Moose::Exporter;
2
3use strict;
4use warnings;
5
6use Class::MOP;
cd00320f 7use namespace::clean 0.08 ();
5bd4db9b 8use Sub::Exporter;
9
10
0338a411 11my %EXPORT_SPEC;
1a601f52 12
a5c426fc 13sub build_import_methods {
14 my $class = shift;
15 my %args = @_;
16
17 my $exporting_package = caller();
18
0338a411 19 $EXPORT_SPEC{$exporting_package} = \%args;
a5c426fc 20
1a601f52 21 my ( $exporter, $exported ) = $class->_build_exporter(
22 exporting_package => $exporting_package,
23 %args
24 );
a5c426fc 25
1a601f52 26 my $import = $class->_make_import_sub(
97a93056 27 $exporting_package, $args{init_meta_args},
1a601f52 28 $exporter
29 );
a5c426fc 30
1a601f52 31 my $unimport = $class->_make_unimport_sub($exported);
a5c426fc 32
33 no strict 'refs';
1a601f52 34 *{ $exporting_package . '::import' } = $import;
a5c426fc 35 *{ $exporting_package . '::unimport' } = $unimport;
36}
37
5bd4db9b 38my %EXPORTED;
a5c426fc 39sub _build_exporter {
5bd4db9b 40 my $class = shift;
41 my %args = @_;
42
a5c426fc 43 my $exporting_package = $args{exporting_package};
5bd4db9b 44
0338a411 45 my @exported_names;
5bd4db9b 46 my %exports;
97a93056 47 for my $name ( @{ $args{with_caller} } ) {
48 my $sub = do { no strict 'refs'; \&{ $exporting_package . '::' . $name } };
49
50 my $wrapped = Class::MOP::subname(
51 $exporting_package . '::' . $name => sub { $sub->( scalar caller(), @_ ) } );
52
53 $exports{$name} = sub { $wrapped };
54
55 push @exported_names, $name;
56 }
57
58 for my $name ( @{ $args{as_is} } ) {
5bd4db9b 59 my $sub;
97a93056 60
5bd4db9b 61 if ( ref $name ) {
62 $sub = $name;
63 $name = ( Class::MOP::get_code_info($name) )[1];
64 }
65 else {
a5c426fc 66 $sub = do { no strict 'refs'; \&{ $exporting_package . '::' . $name } };
5bd4db9b 67
0338a411 68 push @exported_names, $name;
5bd4db9b 69 }
70
71 $exports{$name} = sub { $sub };
72 }
73
0338a411 74 my $exporter = Sub::Exporter::build_exporter(
5bd4db9b 75 {
76 exports => \%exports,
77 groups => { default => [':all'] }
78 }
79 );
5bd4db9b 80
0338a411 81 return $exporter, \@exported_names;
5bd4db9b 82}
83
1a601f52 84sub _make_import_sub {
85 my $class = shift;
86 my $exporting_package = shift;
87 my $init_meta_args = shift;
88 my $exporter = shift;
89
90 return sub {
91 my $caller = Moose::Exporter->_get_caller(@_);
92
93 # this works because both pragmas set $^H (see perldoc perlvar)
94 # which affects the current compilation - i.e. the file who use'd
95 # us - which is why we don't need to do anything special to make
96 # it affect that file rather than this one (which is already compiled)
97
98 strict->import;
99 warnings->import;
100
101 # we should never export to main
102 if ( $caller eq 'main' ) {
103 warn
104 qq{$exporting_package does not export its sugar to the 'main' package.\n};
105 return;
106 }
107
108 if ( $exporting_package->can('_init_meta') ) {
109 $exporting_package->_init_meta(
110 for_class => $caller,
97a93056 111 %{ $init_meta_args || {} }
1a601f52 112 );
113 }
114
115 goto $exporter;
116 };
117}
118
119sub _get_caller {
120 # 1 extra level because it's called by import so there's a layer
121 # of indirection
122 my $offset = 1;
123
124 return
125 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
126 : ( ref $_[1] && defined $_[1]->{into_level} )
127 ? caller( $offset + $_[1]->{into_level} )
128 : caller($offset);
129}
130
131sub _make_unimport_sub {
132 my $class = shift;
133 my $exported = shift;
134
135 # [12:24] <mst> yes. that's horrible. I know. but it should work.
136 #
137 # This will hopefully be replaced in the future once
138 # namespace::clean has an API for it.
139 return sub {
140 @_ = ( 'namespace::clean', @{$exported} );
141
142 goto &namespace::clean::import;
143 };
144}
145
5bd4db9b 1461;
2f29843c 147
148__END__
149
150=head1 NAME
151
152Moose::Exporter - make an import() and unimport() just like Moose.pm
153
154=head1 SYNOPSIS
155
156 package MyApp::Moose;
157
158 use strict;
159 use warnings;
160
161 use Moose ();
162 use Moose::Exporter;
163
164 Moose::Exporter->build_export_methods(
165 export => [ 'sugar1', 'sugar2', \&Some::Random::thing ],
166 init_meta_args => { metaclass_class => 'MyApp::Meta::Class' ],
167 );
168
169 # then later ...
170 package MyApp::User;
171
172 use MyApp::Moose;
173
174 has 'name';
175 sugar1 'do your thing';
176 thing;
177
178 no MyApp::Moose;
179
180=head1 DESCRIPTION
181
182This module encapsulates the logic to export sugar functions like
183C<Moose.pm>. It does this by building custom C<import> and C<unimport>
184methods for your module, based on a spec your provide.
185
186It also lets your "stack" Moose-alike modules so you can export
187Moose's sugar as well as your own, along with sugar from any random
188C<MooseX> module, as long as they all use C<Moose::Exporter>.
189
190=head1 METHODS
191
192This module provides exactly one public method:
193
194=head2 Moose::Exporter->build_import_methods(...)
195
196When you call this method, C<Moose::Exporter> build custom C<import>
197and C<unimport> methods for your module. The import method will export
198the functions you specify, and you can also tell it to export
199functions exported by some other module (like C<Moose.pm>).
200
201The C<unimport> method cleans the callers namespace of all the
202exported functions.
203
204This method accepts the following parameters:
205
206=over 4
207
97a93056 208=item * with_caller => [ ... ]
209
210This a list of function I<names only> to be exported wrapped and then
211exported. The wrapper will pass the name of the calling package as the
212first argument to the function. Many sugar functions need to know
213their caller so they can get the calling package's metaclass object.
214
215=item * as_is => [ ... ]
2f29843c 216
217This a list of function names or sub references to be exported
218as-is. You can identify a subroutine by reference, which is handy to
219re-export some other module's functions directly by reference
220(C<\&Some::Package::function>).
221
222=item * init_meta_args
223
224...
225
226=back
227
228=head1 AUTHOR
229
230Dave Rolsky E<lt>autarch@urth.orgE<gt>
231
232This is largely a reworking of code in Moose.pm originally written by
233Stevan Little and others.
234
235=head1 COPYRIGHT AND LICENSE
236
237Copyright 2008 by Infinity Interactive, Inc.
238
239L<http://www.iinteractive.com>
240
241This library is free software; you can redistribute it and/or modify
242it under the same terms as Perl itself.
243
244=cut