use Smart::Commentsやっぱいらないんじゃね?w

[perl] use Smart::Comments - Bulknews::Subtech - subtech
use Smart::Commentsはいらないと思う - ヒルズで働く@robarioの技ログ
> グローバルフィルターみたいに働くうまい仕組みは無いですかねぇ。

というわけで、各ファイルに自動的に「use Smart::Comments」を埋め込めばできるかな〜と思ってめちゃくちゃなスクリプトをでっちあげてみた。
先に言っておきますが、こんなことするぐらいなら素直に「use Smart::Comments」した方が良いと思います。タイトルはネタです。

「use Smart::Comments」が無いFoo.pm

package Foo;
sub run {
    ### This is Foo...
}
1;

を呼び出すmain.pl

use Foo;
Foo->run;

を実行するときに、-MGlobalSmartComments=Fooを指定して実行すると

% perl -MGlobalSmartComments=Foo main.pl

### This is Foo...

Foo.pmでSmart::Commentsが有効になります。



GlobalSmartComments.pmは見ての通り、精一杯の力技w
perldoc -mlでソースの場所を特定して、/tmp以下に「use Smart::Comments」を挿入しながらコピーしています。コピーした先を@INCの先頭に入れているので、「use Smart::Comments」が付いている方のモジュールが読み込まれるようになります。

  • 階層掘ってないので「::」を含むモジュールが動きません。(ただの手抜き)
  • perldocを呼び出しているので遅い
  • 「use Module ...;」の引数が無視されている
  • UNIX系コマンド(cat,echo)が必要(ただの手抜き)

あ・・・最初ソースフィルタで何とかなると思ってFilter::Simpleを使っていましたけど、それは無理だから各ファイルに「use Smart::Comments」が必要なんですよね。。。
Filter::Simple使わずにGlobalSmartComments::importで全部やればできますね。ということで後でちょっとやってます。やってみました→use Smart::Commentsをソースに書かずに有効にする方法

本当にネタのつもりなので、突っ込みはお手柔らかに・・・

package GlobalSmartComments;
use strict;
use warnings;

use UNIVERSAL::require;
use List::Util qw(first);

my @modules;
my $inc = '/tmp/SCG';

sub import {
    my $class = shift;
    @modules = @_;
    mkdir $inc;
    unshift @INC, $inc;
}

use Filter::Simple sub {
    s{(\s?use\s+([^;]+))}{
        my $all = $1;
        my $args = $2;
        if (first {$args =~ /$_/} @modules) {
            'BEGIN{' . __PACKAGE__ . "::use('$args');}";
        } else {
            $all;
        }
    }egmsx;
};

sub use {
    my $module = shift;

    my $src = `perldoc -ml $module`;
    chomp $src;
    my $dest = $inc . '/' . $module . '.pm';

    `echo 'use Smart::Comments;\n' | cat - $src > $dest`;

    package main;
    $module->use;
}

1;