flymake-perlをエラーなく実行するためにやっておくべきこと
ごちゃごちゃしてきたので、別エントリで。
(前回までのあらすじ)
tramp起動時にflymake-perlが有効になってしまうことに業を煮やした僕が、xなんとか氏(g:emacs:id:xcezx)のツッコミを受けながらflymakeのコードをちょっとずつ読んで、ついに原因を特定する。
flymake.elの623行目でflymake-post-syntax-checkという関数が定義されていて、ここに後処理が書いてあります。flymake-perl時にtrampが有効になってしまうのは、flymake-check-was-interruptedという変数がtrueになってしまい、645行目の
(flymake-report-status nil ""))) ; "STOPPED"
という処理に飛んでしまうからです。このflymake-report-statusという関数は1287行目で定義されていて、
(defun flymake-report-status (e-w &optional status) "Show status in mode line." (when e-w (setq flymake-mode-line-e-w e-w)) (when status (setq flymake-mode-line-status status)) (let* ((mode-line " Flymake")) (when (> (length flymake-mode-line-e-w) 0) (setq mode-line (concat mode-line ":" flymake-mode-line-e-w))) (setq mode-line (concat mode-line flymake-mode-line-status)) (setq flymake-mode-line mode-line) (force-mode-line-update)))
とまあ、色々設定しなおしたのちにforce-mode-line-update関数を評価しておしまいです。なお、643-4行目にはflymake-check-was-interruptedがnilの時の処理が書いてあって、
(flymake-report-fatal-status "CFGERR" (format "Configuration error has occured while running %s" command))
と、エラー時の処理に飛ぶようになってます。このflymake-report-fatal-statusという関数は1309行目で定義されていて、
(defun flymake-report-fatal-status (status warning) "Display a warning and switch flymake mode off." (when flymake-gui-warnings-enabled (flymake-display-warning (format "Flymake: %s. Flymake will be switched OFF" warning)) ) (flymake-mode 0) (flymake-log 0 "switched OFF Flymake mode for buffer %s due to fatal status %s, warning %s" (buffer-name) status warning))
と、ここでは「(flymake-mode 0)」というのが評価され、flymakeを無効にしていることがわかります。
ここで、2つの選択肢がでてくると思います。まず何よりの目的は、tramp起動時はflymakeを無効にすることです。ただ、そのための実装方法として
- わざわざflymake-check-was-interruptedをtrueにせず、普通にエラー処理させて無効にする
- わざわざdefadviceつけてまで処理してるので、大元の設定を書いた人の意思を尊重して、flymake-report-status関数の方を変更する
前者の方が設定が圧倒的に楽ですが、プロンプトはウザいし、exit-statusが1以上なのにinterruptedがtrueなのは基本的にエラーなのではないかと思うので、僕はあえて後者の方を選択しています。もう一度645行目を見てもらうと分かるように、
(flymake-report-status nil ""))) ; "STOPPED"
第1引数にはnilが渡っています。検索してみる限り、flymake-report-status関数を呼び出しているところで、第1引数がnilなのはここしかないので、これを利用しない手はないと思います。そこを踏まえて、flymake-report-status関数に以下の処理を追加しました。
(defadvice flymake-report-status (before flymake-quite-report-status (e-w &optional status)) (if (not e-w) (progn (flymake-mode 0) (flymake-log 0 "switched OFF Flymake mode due to unknown fatal status (maybe tramp is running)")))) (ad-activate 'flymake-report-status)
これをid:antipop氏の例の設定の前に書き加えておけば、tramp起動時にもプロンプトは出ず、かつflymakeも無効になります。なお、コメントやmessageに出力する文章は殆ど推敲なしなので、もっといい文言が欲しいです。