Acme-SubstituteSubs
view release on metacpan or search on metacpan
lib/Acme/SubstituteSubs.pm view on Meta::CPAN
sub set {
shift if Devel::Caller::called_as_method;
my $fqfunc = shift;
my $code = shift;
my ($packagename, $methodname) = ($fqfunc =~ m/(.*)::(.*)/, 'main', $fqfunc);
defined $code or die 'set($qualified_function_name, $replacement_code)';
# if code is a CODE ref, deparse it
# XXX extra points for keeping values for lexicals
$code = B::Deparse->new->coderef2text($code) if ref($code) and ref($code) eq 'CODE';
if($code =~ m/^{/) {
$code = qq<sub $code>; # happens when B::Deparse kicks in
} elsif($code =~ m/^\s*sub\s+{/) {
$code =~ s/sub/sub $methodname /; # untested codepath alert
} elsif($code !~ m/^\s*sub/) {
$code = qq<sub $methodname { $code }>;
}
# $code .= "\n" unless $code =~ m/\n$/s;
# STDERR->print("saving updates to $RealScript\n");
open my $fh, '>', $RealScript.'.new' or die $!;
my $currentpackage = 'main';
my $foundit = 0;
my $doc = PPI::Document->new($RealScript) or die PPI::Document->errstr;
for my $child ($doc->children) {
if($child->isa('PPI::Statement::Sub')) {
if(! $foundit and $child->name eq $methodname and $currentpackage eq $packagename) {
$fh->print($code); # instead of $child->content
$foundit = 1;
} else {
$fh->print($child->content);
}
} elsif($child->isa('PPI::Statement::Package')) {
if(! $foundit and $currentpackage eq $packagename) {
$fh->print($code);
$foundit = 1;
}
$currentpackage = $child->namespace;
$fh->print($child->content);
} else {
$fh->print($child->content) or die;
}
}
if(! $foundit ) {
# at the end of the file and still haven't found the package/sub? just append it.
if($currentpackage ne $packagename) {
$fh->print(qq{\npackage $packagename;\n});
}
$fh->print($code);
}
$fh->close;
rename $RealScript, $RealScript.'.last';
rename $RealScript.'.new', $RealScript or do {
warn "renaming new pl file into place as ``$RealScript'' failed: $!";
};
}
sub list_both {
shift if Devel::Caller::called_as_method;
my @packages;
my @subs;
my $doc = PPI::Document->new($RealScript) or die PPI::Document->errstr;
my $currentpackage = 'main::';
push @packages, $currentpackage;
for my $child ($doc->children) {
if($child->isa('PPI::Statement::Sub')) {
push @subs, $currentpackage . $child->name;
} elsif($child->isa('PPI::Statement::Package')) {
$currentpackage = $child->namespace . '::';
push @packages, $currentpackage;
}
}
return \@subs, \@packages;
}
sub list {
return @{ list_both()->[0] };
}
sub list_packages {
return @{ list_both()->[1] };
}
1;
( run in 1.592 second using v1.01-cache-2.11-cpan-437f7b0c052 )