• このエントリーをはてなブックマークに追加

はじめに

を参考に,pmver Foo::Bar でモジュールのバージョンを確認したり,pm Foo::Bar でモジュールのソースコードをエディタで見たり...

こちらで初めて知った perldoc -l をラップした pmwhere Foo::Bar でモジュールのありかを調べたりと,次のようなシェルスクリプト関数を定義しています:

function pm() { [ -n "$1" ] && PERLDOC_PAGER=vim perldoc -m $1 }
function pmver () { perl -Ilocal/lib/perl5 -M$1 -le "print \$$1::VERSION" }
function pmwhere () { perldoc -l $1 }

最近は,次の 2点:

  • アプリケーションやプロジェクト(以下,アプリケーション)ごとに libset を作る( perlbrew lib create @myapp するなど)
  • 依存する非標準モジュールはすべて carton で /path/to/myapp/local 下に閉じ込めるようにする

を心がけていたりするわけですが,carton 管理下のモジュールに対しては,先のシェルスクリプト関数はうまく機能してくれません:

% cd /path/to/myapp
% ls local/lib/perl5/Net/Twitter/Lite.pm
local/lib/perl5/Net/Twitter/Lite.pm
% pm Net::Twitter::Lite
No module found for "Net::Twitter::Lite".

夕食を買い出すのを忘れて少しばかり試行錯誤した結果,とりあえず目的を果たせるようになったっぽいので,その結果だけでも記録しておきます.

コンセプト的な

現在(関数を呼び出した)のディレクトリから(上階層側に)直近の「直下に carton.lock を含むディレクトリ」を,アプリケーションのベースディレクトリとし,その下にある local/lib/perl5 を考慮する,という感じです.

もし carton.lock を含むディレクトリが見つからなければ, carton で管理しているアプリケーションではないと判断し,通常どおりに扱います.

共通処理: carton.lock を含むディレクトリを見つける

_lookup_carton_lock として,次のように書いてみました:

function _lookup_carton_lock() {
    echo $(perl -e 'my $curr=$ENV{PWD}; while(!-f "$curr/carton.lock" && $curr ne "/"){ ($curr.="/..")=~s!/[^/]+/\.\.!!; chdir($curr||="/")}; print $curr')
}

HOGE=$(_lookup_carton_lock) みたいな感じで使います.

ちなみに,Perl のコードの部分を見やすくすると次のとおり:

my $curr = $ENV{PWD};
while( ! -f "$curr/carton.lock" && $curr ne "/" ) {
    ($curr .= "/..") =~ s!/[^/]+/\.\.!!;
    chdir ($curr ||= "/");
};
print $curr;

最初は Perl を含めずに $(cd ... && pwd) を使いまくって書いてましたが,そのたびに smartcd が反応してやたらと遅くなるため,上記のようになりましたとさ.

pmwhere 〜そのモジュールはどこに?〜

指定したモジュールがどこにあるのかを教えてくれます.perldoc -l のそれ向け版です:

function pmwhere () {
    _ROOT=$(_lookup_carton_lock)
    if [ -f "$_ROOT/carton.lock" ]; then
        carton exec -I$_ROOT/local/lib/perl5 -- perldoc -l $1
    else
        perldoc -l $1
    fi
}

例えば,ホームディレクトリで:

% cd ~
smartcd: running /Users/issm/.smartcd/scripts/Users/issm/bash_enter
- perlbrew use 5.12.4
% pmwhere Plack
/Users/issm/perl5/perlbrew/perls/perl-5.12.4/lib/site_perl/5.12.4/Plack.pm
% pmwhere LWP::Protocol::Net::Curl
No documentation found for "LWP::Protocol::Net::Curl".

例えば,carton で管理しているとあるアプリケーション下で:

% cd /ptah/to/myapp
smartcd: running /Users/issm/.smartcd/scripts/path/to/myapp/bash_enter
- perlbrew use 5.14.3@myapp
% pmwhere Plack
/path/to/myapp/local/lib/perl5/Plack.pm
% pmwhere LWP::Protocol::Net::Curl
/path/to/myapp/local/lib/perl5/LWP/Protocol/Net/Curl.pm

pmdoc 〜それ向け perldoc〜

perldoc のそれ向け版です:

function pmdoc() {
    _ROOT=$(_lookup_carton_lock)
    if [ -f "$_ROOT/carton.lock" ]; then
        carton exec -I$_ROOT/local/lib/perl5 -- perldoc $1
    else
        perldoc $1
    fi
}

モジュールは存在していても,perldoc は見つけてくれません:

% cd /path/to/myapp/tmpl/admin
smartcd: running /Users/issm/.smartcd/scripts/path/to/myapp/bash_enter
- perlbrew use 5.14.3@myapp
ls /path/to/myapp/local/lib/perl5/LWP/Protocol/Net/Curl.pm
/path/to/myapp/local/lib/perl5/LWP/Protocol/Net/Curl.pm
% PERLDOC_PAGER="head -20" perldoc LWP::Protocol::Net::Curl
No documentation found for "LWP::Protocol::Net::Curl".

pmdoc では見つかります:

% PERLDOC_PAGER="head -20" pmdoc LWP::Protocol::Net::Curl
LWP::Protocol::Net::CuUser)Contributed Perl DocumenLWP::Protocol::Net::Curl(3)
 
 
 
NAME
       LWP::Protocol::Net::Curl − the power of libcurl in the palm of your
       hands!
 
VERSION
       version 0.011
 
SYNOPSIS
           #!/usr/bin/env perl;
           use common::sense;
 
           use LWP::Protocol::Net::Curl;
           use WWW::Mechanize;
 
           ...

pmver 〜モジュールのバージョンを確認する〜

function pmver () {
    _ROOT=$(_lookup_carton_lock)
    if [ -f "$_ROOT/carton.lock" ]; then
        perl -I$_ROOT/local/lib/perl5 -M$1 -le "print \$$1::VERSION"
    else
        perl -M$1 -le "print \$$1::VERSION"
    fi
}

例えば,ホームディレクトリで:

% cd ~
smartcd: running /Users/issm/.smartcd/scripts/Users/issm/bash_enter
- perlbrew use 5.12.4
% pmver Plack
1.0013
% pmver LWP::Protocol::Net::Curl
Can't locate LWP/Protocol/Net/Curl.pm in @INC (@INC contains: /Users/issm/local/lib/site_perl/5.12.4/darwin-2level /Users/issm/perl5/perlbrew/perls/perl-5.12.4/lib/site_perl/5.12.4/darwin-2level /Users/issm/perl5/perlbrew/perls/perl-5.12.4/lib/site_perl/5.12.4 /Users/issm/perl5/perlbrew/perls/perl-5.12.4/lib/5.12.4/darwin-2level /Users/issm/perl5/perlbrew/perls/perl-5.12.4/lib/5.12.4 .).
BEGIN failed--compilation aborted.

例えば, carton で管理しているとあるアプリケーション下で:

% cd /ptah/to/myapp
smartcd: running /Users/issm/.smartcd/scripts/path/to/myapp/bash_enter
- perlbrew use 5.14.3@myapp
% pmver Plack
1.0015
% pmver LWP::Protocol::Net::Curl
0.011
% pmver Foobar
Can't locate Foobar.pm in @INC (@INC contains: /path/to/myapp/local/lib/perl5/darwin-2level /path/to/myapp/local/lib/perl5 /Users/issm/.perlbrew/libs/perl-5.14.3@myap/lib/perl5/darwin-2level /Users/issm/.perlbrew/libs/perl-5.14.3@myapp/lib/perl5 /Users/issm/local/lib/site_perl/5.12.4/darwin-2level /Users/issm/perl5/perlbrew/perls/perl-5.14.3/lib/site_perl/5.14.3/darwin-2level /Users/issm/perl5/perlbrew/perls/perl-5.14.3/lib/site_perl/5.14.3 /Users/issm/perl5/perlbrew/perls/perl-5.14.3/lib/5.14.3/darwin-2level /Users/issm/perl5/perlbrew/perls/perl-5.14.3/lib/5.14.3 .).
BEGIN failed--compilation aborted.

pm 〜モジュールのソースコードを(vim で)見る〜

これについては,先の pmwhere を利用して簡単に書けました:

function pm() {
    _PMWHERE=$([ -n "$1" ] && pmwhere $1)
    if [ $? = 0 ]; then
        vim $_PMWHERE
    fi
}

ちょこっと問題も

ただし,_lookup_carton_lock 関数にちょっと問題があるみたいで,

PROMPT 系環境変数に %~ を指定していると,特定の処理のときに,その部分に影響を与えてしまうようです:

ss-1360938796

ちなみに,%/ であれば問題ないみたいです:

ss-1360938859

おわりに

以上,carton で管理しているアプリケーションに含まれている CPAN モジュールについても,バージョンやソースコードなどを確認できるように,シェルスクリプトの関数を書き換えてみたお話でした.俺得.

しかしよく考えたら,perldoc のオプションや環境変数,smartcd なんかをうまく使えば,もっとスマートにできそうですね.まぁいいや.