How can I use Smart::Comments in a module I load without changing its source?
How can I specify that Smart::Comments be loaded for my original script, as well as for any of the modules it directly loads. However, since it is a source-filter, it would probably wreck havoc if applied to every module loaded by every other loaded module.
For example, my script includes
use Neu::Image;
I would like to load Smart::Comments
for Neu::Image
as well, but specifying
$ perl -MSmart::Comments script.pl
does not load Smart::Comments
for Neu::Image
.
This behavior is described in the Smart::Comments documentation:
If you're debugging an application you can also invoke it with the module from the command-line:
perl -MSmart::Comments $application.pl
Of course, this only enables smart comments in the application file itself, not in any modules that the application loads.
A few other things that I've looked at already:
- Perl Command-Line Options
- perldoc perlrun (I searched it for the word "module")
WORKAROUND As gbacon mentions, Smart::Comments provides an environment variable option that would allow turning it on or off. However, I would like to be able to turn it on without modifying the original source, if possible开发者_如何转开发.
You almost certainly want to add use Smart::Comments
to modules that contain such and then flip the switch in your environment by setting $Smart_Comments
appropriately.
Stash-munging, import
-hijacking monkey-patching is madness.
But maybe you're into that sort of thing. Say you have Foo.pm
:
package Foo;
use Exporter 'import';
our @EXPORT = qw/ foo /;
#use Smart::Comments;
sub foo {
my @result;
for (my $i = 0; $i < 5; $i++) {
### $i
push @result => $i if $i % 2 == 0;
}
wantarray ? @result : \@result;
}
1;
Ordinary usage:
$ perl -MFoo -e 'print foo, "\n"' 024
Ordinary is dull and boring, of course. With run-foo
, we take bold, dashing steps!
#! /usr/bin/perl
use warnings;
use strict;
BEGIN {
unshift @INC => \&inject_smart_comments;
my %direct;
open my $fh, "<", $0 or die "$0: open: $!";
while (<$fh>) {
++$direct{$1} if /^\s*use\s+([A-Z][:\w]*)/;
}
close $fh;
sub inject_smart_comments {
my(undef,$path) = @_;
s/[\/\\]/::/g, s/\.pm$// for my $mod = $path;
if ($direct{$mod}) {
open my $fh, "<", $path or die "$0: open $path: $!";
return sub {
return 0 unless defined($_ = <$fh>);
s{^(\s*package\s+[A-Z][:\w]*\s*;\s*)$}
{$1 use Smart::Comments;\n};
return 1;
};
}
}
}
use Foo;
print foo, "\n";
(Please pardon the compactness: I shrunk it so it would all fit in an unscrolled block.)
Output:
$ ./run-foo ### $i: 0 ### $i: 1 ### $i: 2 ### $i: 3 ### $i: 4 024
¡Viva!
With @INC
hooks we can substitute our own or modified sources. The code watches for attempts to require
modules directly used by the program. On a hit, inject_smart_comments
returns an iterator that yields one line at a time. When this crafty, artful iterator sees the package declaration, it appends an innocent-looking use Smart::Comments
to the chunk, making it appear as though it were in the module's source all along.
By trying to parse Perl code with regular expressions, the code will break if the package declaration isn't on a line by itself, for example. Season to taste.
It doesn't seem like this idea makes any sense. If you are utilizing Smart::Comments
in a module, why would you not want to use Smart::Comments
in that module's source? Even if you could get Smart::Comments
to apply to all modules loaded in a script via -M
, it probably wouldn't be a good idea because:
- You're obfuscating the fact that your modules are using smart comments by not including the
use
line in their source. - You could potentially introduce bizarre behavior from modules you
use
in your script which happen to have what look like smart comments, but aren't really. If a module doesn't contain smart comments, you should not force them down its throat.
As gbacon said, the right way to do this is to use
the module in each of your modules that make use of it, and then suppress them with an environment variable when you don't want the output.
Also as he said, it's still probably possible to do this with some "Stash-munging, import-hijacking monkey-patching" madness, but that's a lot of work. I don't think anyone is going to put the effort into giving you a solution along those lines when it is not a good idea in the first place.
精彩评论