Kentaro Kuribayashi's blog

Software Engineering, Management, Books, and Daily Journal.

perlbrew.elとProject::Libsを使ったflymakeの設定

同僚が、perlbrewを使っている時に、MacのCocoa Emacsで意図したperlのバージョンが動かなくて困ってたので、flymakeの設定を見直してみた。

perlbrew.el

まず、Cocoa Emacsから利用するperlのバージョンをあらかじめ指定できるよう、以下のような簡単なelispをでっち上げた。

こんな感じで書いておけば、起動時に`perlbrew switch 5.12.3'が実行されるので、いい感じに使える。

(require 'perlbrew)
(perlbrew-switch "perl-5.12.3")

まあ、(shell-command "perlbrew switch perl-5.12.3")するのと同じなので、perlbrewを実行したいだけなら、わざわざ使わなくてもいいけど。

flymakeの設定

んでもって、flymakeの設定。以下の2つの要件がある。

  • @INCをいい感じに追加する
  • perlのバージョン

まず、@INCについては、会社のプロジェクトでは、gitを使っていて、依存モジュールを$PROJECT_ROOT/modules/*以下に置いてあるので、それらのパスも@INCに入れなければならない。Project::Libsを使えばよろしい。

perlのバージョンについては、perlbrewしてあるのでそれが使われるんだろうと思っていたら、どうもそれが使われないような感じ……。そこで、perlbrew.elがswitchした時に`perlbrew-current-perl-path'という変数に現在のperlへのパスを記録しているので、その変数のgetter関数を呼び出すことにする。そうしておくと、perlbrew-switchした後は、switch後のperlでflymakeが走るようになる(ただし、次回のcperl-mode-hook起動時以降。また、perlのバージョンはEmacs内でグローバル)。

そんなわけで、以下の通り、非常に簡潔に設定できた。

(require 'flymake)

(add-to-list 'flymake-allowed-file-name-masks
             '("\\(\\.t\\|\\.psgi\\)$" flymake-perl-init))

(defun flymake-perl-init ()
  (let* ((temp-file (flymake-init-create-temp-buffer-copy
                     'flymake-create-temp-inplace))
         (local-file (file-relative-name
                      temp-file
                      (file-name-directory buffer-file-name))))
    (list (perlbrew-get-current-perl-path) (list "-MProject::Libs" "-wc" local-file))))

(add-hook 'cperl-mode-hook (lambda () (flymake-mode t)))