Kesin's diary

プログラミングの記事がメインです

VimでのCartonを使ったPerlの開発

最近Perlを書くことになりましたKesinです。Pythonが懐かしいです。

言語が変わっても相変わらずVimを愛用していて、文法チェックができるsyntastic *1と、Vimで書いているスクリプトをすぐに実行できるvim-quickrunには相変わらずお世話になっています。

PerlでWebアプリとかを書くときは、CartonというRubyのBundlerのような仕組みを使うのが今どきらしいのですが、上の2つのプラグインがCarton環境以下で上手く動いてくれないので、Cartonに対応させる.vimrcを書いてみました。

" thinca/vim-localrcをインストールし、Cartonで管理しているAmon2プロジェクトなどのlibがあるディレクトリに.local.vimrcとして置く

let carton_path = system('carton exec perl -e "print join(q/,/,@INC)"')
let lib_path = fnamemodify(finddir("lib", ";"), ":p")
let g:syntastic_perl_lib_path = join([carton_path, lib_path], ',')

let g:quickrun_config = {
\   'perl' : {
\       'cmdopt': '-Ilib',
\       'exec': 'carton exec perl %o %s',
\    },
\}

これを.local.vimrcという名前でCartonで管理しているディレクトリのトップに保存し、vim-localrcプラグインを導入すると、syntasticとquickrunがCarton対応になります。 自分はGithubにアップしてるdotfilesに.local.vimrcという名前で保存しておき、必要なときにプロジェクトのディレクトリにコピーするという使い方をしています。

syntasticの問題

syntasticは文法チェックにシステムのPerlperl -cを実行した結果を使うので、CartonでインストールしたモジュールがシステムのPerlにインストールされていないと、下のような感じで先頭のuse文で盛大にエラーを吐いてくれます。

f:id:Kesin:20140623000840p:plain

さらに困るのが、以下のようなディレクトリ構成のときに、例えばMyAppにcdしてからControlelr.pmでModelをuseしようとすると、やはりパスが通っていないということでエラーが出力されてしまいます。 libと同じ階層でperl -lで実行すれば問題は無いので、カレントディレクトリが違うだけで文法チェックで怒られるのは辛い感じです・・・

-- lib
  |-- MyApp.pm
  |-- MyApp
     |-- Controller.pm
     |-- Model.pm
     |-- View.pm
# Controller.pm
use MyApp::Model;

...

vim-quickrunの問題

quickrunの方も原因は同じで、Cartonでモジュールを管理しているlocalディレクトリにパスが通っていないのでCartonでインストールしたモジュールを使ってくれません。

原理

先に示した設定をすると、syntasticとquickrunがCartonのパスを参照するようになり、問題は解消されます。

syntasticの方は、Cartonを使った時のパス(@INC)と、libディレクトリをsyntasticの設定に渡すことで解決しています。lib_path = fnamemodify(finddir("lib", ";"), ":p")はカレントディレクトリより上の階層にあるlibディレクトリのパスを返すということをしています。

自分も最初はqiitaのyuku_tさんの記事を参考にしてプロジェクトディレクトリごとに手動でフルパスを設定していたのですが、汎用性が無かったのでパスが自動で設定されるようにしました。

quickrunは見たまんまですが、Carton exec perlで実行するように設定しています。%oはcmdopt, %sは実行するスクリプトのパスに展開されます。

まとめ

というわけで、プラグインですらない非常に単純な設定ですが、syntasticとquickrunをCartonに対応させたという話でした。
2つのプラグインとCartonの相性の悪さにイライラしていた人は、ストレスから解消されると思います。

参考

*1:デフォルトだとPerlのチェックは無効化されているので注意が必要です。公式READMEのFAQ参照