small importing doc fix, import default works also with []
[p5sagit/Package-Variant.git] / lib / Package / Variant.pm
index 7e0cbe0..9455301 100644 (file)
@@ -1,6 +1,7 @@
 package Package::Variant;
 
 use strictures 1;
+use Carp qw( croak );
 
 our %Variable;
 
@@ -21,8 +22,10 @@ sub import {
   };
   *{"${target}::import"} = sub {
     my $target = caller;
+    my (undef, %arg) = @_;
+    my $as = defined($arg{as}) ? $arg{as} : $last;
     no strict 'refs';
-    *{"${target}::${last}"} = sub {
+    *{"${target}::${as}"} = sub {
       $me->build_variant_of($variable, @_);
     };
   };
@@ -37,15 +40,39 @@ sub import {
   }
 }
 
+my $sanitize_importing = sub {
+  my ($me, $spec) = @_;
+  return []
+    unless defined $spec;
+  return [map [$_ => $spec->{$_}], keys %$spec]
+    if ref $spec eq 'HASH';
+  croak q{The 'importing' option has to be either a hash or array ref}
+    unless ref $spec eq 'ARRAY';
+  my @specced = @$spec;
+  my @imports;
+  while (@specced) {
+    push @imports, [shift(@specced), shift(@specced)];
+  }
+  return \@imports;
+};
+
 sub build_variant_of {
   my ($me, $variable, @args) = @_;
   my $variant_name = "${variable}::_Variant_".++$Variable{$variable}{anon};
-  my $import = $Variable{$variable}{args}{importing} || {};
+  my $import = $me
+    ->$sanitize_importing($Variable{$variable}{args}{importing});
   my $setup = join("\n",
     "package ${variant_name};",
     (map sprintf(
-      q!use %s @{$import->{'%s'}||[]};!, $_, quotemeta($_),
-    ), keys %$import),
+      q!use %s %s;!,
+      $import->[$_][0],
+      not(defined $import->[$_][1])
+        ? ''
+        : sprintf(
+          q!@{$import->[%d][1]}!,
+          $_,
+        ),
+    ), 0..$#$import),
     "1;",
   );
   eval $setup
@@ -76,7 +103,7 @@ Package::Variant - Parameterizable packages
   use strictures 1;
   use Package::Variant
     # what modules to 'use'
-    importing => { 'Moo::Role' => [] },
+    importing => { 'Moo::Role' => undef },
     # proxied subroutines
     subs => [qw( has around before after extends )],
 
@@ -134,7 +161,7 @@ to be C<use>d as keys, and array references containing the import
 arguments as values. These packages will be imported into every new
 variant, and need to set up every declarative subroutine you require to
 build your variable package. The next option will allow you to use these
-functions.
+functions. See L</importing> for more options.
 
 The L</subs> option is an array reference of subroutine names that are
 exported by the packages specified with L</importing>. These subroutines
@@ -176,7 +203,8 @@ your package.
   use My::Variant;
   my $new_variant_package = Variant( @variant_arguments );
 
-The package is now fully initialized and used.
+The package is now fully initialized and used. You can import the
+subroutine under a different name by specifying an C<as> argument.
 
 =head2 Dynamic creation of variant packages
 
@@ -205,6 +233,15 @@ containing import arguments. The packages will be C<use>d with the given
 arguments by every variation before the L</make_variant> method is asked
 to create the package.
 
+If import order is important to you, you can also pass the C<importing>
+arguments as a flag array reference:
+
+  use Package::Variant
+    importing => [ PackageA => [], PackageB => [] ];
+
+If you want to import whatever the package exports by default, you can
+also pass C<undef> instead of an empty array reference.
+
 =head2 subs
 
 An array reference of strings listing the names of subroutines that should
@@ -239,6 +276,19 @@ This method is provided for you. It will allow a user to C<use> your
 package and receive a subroutine taking C<@arguments> defining the variant
 and returning the name of the newly created variant package.
 
+The following options can be specified when importing:
+
+=over
+
+=item * B<as>
+
+  use Some::Variant::Package as => 'Foo';
+  my $variant_package = Foo( @arguments );
+
+Exports the generator subroutine under a different name than the default.
+
+=back
+
 =head1 C<Package::Variant> METHODS
 
 These methods are available on C<Package::Variant> itself.