Commit | Line | Data |
5bd4db9b |
1 | package Moose::Exporter; |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
6 | use Class::MOP; |
cd00320f |
7 | use namespace::clean 0.08 (); |
5bd4db9b |
8 | use Sub::Exporter; |
9 | |
10 | |
11 | sub get_caller{ |
12 | # 1 extra level because it's called by import so there's a layer of indirection |
13 | my $offset = 1; |
14 | |
15 | return |
16 | (ref $_[1] && defined $_[1]->{into}) |
17 | ? $_[1]->{into} |
18 | : (ref $_[1] && defined $_[1]->{into_level}) |
19 | ? caller($offset + $_[1]->{into_level}) |
20 | : caller($offset); |
21 | } |
22 | |
0338a411 |
23 | my %EXPORT_SPEC; |
a5c426fc |
24 | sub build_import_methods { |
25 | my $class = shift; |
26 | my %args = @_; |
27 | |
28 | my $exporting_package = caller(); |
29 | |
0338a411 |
30 | $EXPORT_SPEC{$exporting_package} = \%args; |
a5c426fc |
31 | |
0338a411 |
32 | my ( $exporter, $exported ) |
33 | = $class->_build_exporter( exporting_package => $exporting_package, |
34 | %args ); |
a5c426fc |
35 | |
36 | my $import = sub { |
37 | my $caller = Moose::Exporter->get_caller(@_); |
38 | |
39 | # this works because both pragmas set $^H (see perldoc perlvar) |
40 | # which affects the current compilation - i.e. the file who use'd |
41 | # us - which is why we don't need to do anything special to make |
42 | # it affect that file rather than this one (which is already compiled) |
43 | |
44 | strict->import; |
45 | warnings->import; |
46 | |
47 | # we should never export to main |
48 | if ( $caller eq 'main' ) { |
49 | warn |
50 | qq{$exporting_package does not export its sugar to the 'main' package.\n}; |
51 | return; |
52 | } |
53 | |
0338a411 |
54 | if ( $exporting_package->can('_init_meta') ) { |
55 | $exporting_package->_init_meta( |
56 | for_class => $caller, |
57 | %{ $args{init_meta_args} || {} } |
58 | ); |
59 | } |
a5c426fc |
60 | |
61 | goto $exporter; |
62 | }; |
63 | |
0338a411 |
64 | # [12:24] <mst> yes. that's horrible. I know. but it should work. |
65 | # |
66 | # This will hopefully be replaced in the future once |
67 | # namespace::clean has an API for it. |
a5c426fc |
68 | my $unimport = sub { |
0338a411 |
69 | @_ = ( 'namespace::clean', @{ $exported } ); |
a5c426fc |
70 | |
0338a411 |
71 | goto &namespace::clean::import; |
a5c426fc |
72 | }; |
73 | |
74 | no strict 'refs'; |
75 | *{ $exporting_package . '::import' } = $import; |
76 | *{ $exporting_package . '::unimport' } = $unimport; |
77 | } |
78 | |
5bd4db9b |
79 | my %EXPORTED; |
a5c426fc |
80 | sub _build_exporter { |
5bd4db9b |
81 | my $class = shift; |
82 | my %args = @_; |
83 | |
a5c426fc |
84 | my $exporting_package = $args{exporting_package}; |
5bd4db9b |
85 | |
0338a411 |
86 | my @exported_names; |
5bd4db9b |
87 | my %exports; |
88 | for my $name ( @{ $args{with_caller} } ) { |
a5c426fc |
89 | my $sub = do { no strict 'refs'; \&{ $exporting_package . '::' . $name } }; |
5bd4db9b |
90 | |
91 | my $wrapped = Class::MOP::subname( |
a5c426fc |
92 | $exporting_package . '::' . $name => sub { $sub->( scalar caller(), @_ ) } ); |
5bd4db9b |
93 | |
94 | $exports{$name} = sub { $wrapped }; |
95 | |
0338a411 |
96 | push @exported_names, $name; |
5bd4db9b |
97 | } |
98 | |
99 | for my $name ( @{ $args{as_is} } ) { |
100 | my $sub; |
101 | |
102 | if ( ref $name ) { |
103 | $sub = $name; |
104 | $name = ( Class::MOP::get_code_info($name) )[1]; |
105 | } |
106 | else { |
a5c426fc |
107 | $sub = do { no strict 'refs'; \&{ $exporting_package . '::' . $name } }; |
5bd4db9b |
108 | |
0338a411 |
109 | push @exported_names, $name; |
5bd4db9b |
110 | } |
111 | |
112 | $exports{$name} = sub { $sub }; |
113 | } |
114 | |
0338a411 |
115 | my $exporter = Sub::Exporter::build_exporter( |
5bd4db9b |
116 | { |
117 | exports => \%exports, |
118 | groups => { default => [':all'] } |
119 | } |
120 | ); |
5bd4db9b |
121 | |
0338a411 |
122 | return $exporter, \@exported_names; |
5bd4db9b |
123 | } |
124 | |
125 | 1; |