Le 17.10.2012 05:19, Ricardo Signes via RT a écrit :
Show quoted text> What you *could* do, however, is write a collector for INIT that would
> pick an alternate installer, detect the case of "group name followed
> by bang-name" and then mark those names for non- installation. It
> should actually be pretty simple, once you see how the pieces fit
> together.
OK, I found a solution following your advice (see code below). It wasn't
actually that simple : I spent some time in the debugger to understand
a) that datastructures are not the same between "import_args" (an array
of arrayrefs to pairs) and "to_import" (a flat array of pairs)
b) that the alternate installer must be given in the initial config; by
the time we reach INIT, it's too late to add an installer into %$config,
because build_exporter() has already created its own copy in "my
$installer" (line 732). So I must always inject a custom installer, and
communicate with INIT through a global variable :-(
Anyway, I reached what I wanted; thanks for the tips. For info, here is
the code :
use Sub::Exporter -setup => {
exports => ...
groups => ...
collectors => { INIT => \&_init },
installer => \&_installer,
};
# customizing Sub::Exporter to support "bang-syntax" (excluding symbols)
{ my @dont_export;
sub _init {
my ($collection, $context) = @_;
my $args = $context->{import_args};
my ($exclude, $regular_args)
= part {!ref $_->[0] && $_->[0] =~ /^!/ ? 0 : 1} @$args;
@$args = @$regular_args;
@dont_export = map {substr($_->[0], 1)} @$exclude;
}
sub _installer {
my ($arg, $to_export) = @_;
my %export_hash = @$to_export;
delete @export_hash{@dont_export};
Sub::Exporter::default_installer($arg, [%export_hash]);
}
}