如何在我加载的模块中使用Smart :: Comments而不更改其源代码?

Chr*_*oms 7 perl command-line module

如何为我的原始脚本以及它直接加载的任何模块指定Smart :: Comments.但是,由于它是一个源过滤器,如果应用于每个其他加载模块加载的每个模块,它可能会造成严重破坏.

例如,我的脚本包括

use Neu::Image;
Run Code Online (Sandbox Code Playgroud)

我想加载Smart::CommentsNeu::Image为好,但指定

$ perl -MSmart::Comments script.pl

不加载Smart::CommentsNeu::Image.

Smart :: Comments文档中描述了此行为:

如果您正在调试应用程序,您也可以使用命令行中的模块调用它:

perl -MSmart::Comments $application.pl
Run Code Online (Sandbox Code Playgroud)

当然,这只能在应用程序文件本身中启用智能注释,而不是在应用程序加载的任何模块中启用.

我已经看过的一些其他事情:

回到顶端|提供反馈替代方法 正如gbacon所提到的,Smart :: Comments提供了一个环境变量选项,允许打开或关闭它.但是,如果可能的话,我希望能够在不修改原始源的情况下打开它.

Gre*_*con 10

您几乎肯定希望添加use Smart::Comments到包含此类的模块,然后通过适当设置在您的环境中翻转开关$Smart_Comments.

藏匿,import劫持猴子修补是疯狂的.

但也许你会遇到那种事情.说你有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;
Run Code Online (Sandbox Code Playgroud)

普通用法:

$ perl -MFoo -e 'print foo, "\n"'
024

当然,平凡无聊乏味.有了run-foo,我们采取大胆,潇洒的步骤!

#! /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";
Run Code Online (Sandbox Code Playgroud)

(请原谅紧凑性:我收缩它所以它都适合未展开的块.)

输出:

$ ./run-foo

### $i: 0

### $i: 1

### $i: 2

### $i: 3

### $i: 4
024

¡万岁!

使用@INC钩子,我们可以替换我们自己的或修改过的来源.代码监视require程序直接使用的模块的尝试.在命中时,inject_smart_comments返回一次产生一行的迭代器.当这个狡猾的,巧妙的迭代器看到包声明时,它use Smart::Comments会向块添加一个无辜的外观,使它看起来好像它一直在模块的源中.

通过尝试使用正则表达式解析Perl代码,例如,如果包声明本身不在一行上,代码将会中断.品尝季节.