Gnusではメールの自動受信がデフォルトでは無効になっている

最近Gnusを使ってみてます。
メールの送受信はできるようになったのですが、どうも受信メールの確認が自動で実行されていないようで、 メールサーバに新着メールが届いても、グループバッファが一向に更新されません。

先に結論

以下の設定を行うことで、新着メールの自動確認が行われグループバッファが更新されるようになります。

(require 'gnus-demon)

(defun my:gnus-setup-demon ()
  (setq gnus-demon-timestep 1)
  (gnus-demon-add-handler 'gnus-demon-scan-news 300 nil))

(add-hook 'gnus-started-hook 'my:gnus-setup-demon t)

上記設定により、5分(300秒)毎に新着メール確認処理が実行されます。
詳しくは以下を。

調査

高機能という触れ込みのGnusにその機能が無い訳はないだろうと思ったんですが。
gnus-group-get-new-newsで新着メール確認ができることはわかったんですが、 それを自動実行することに関しての情報が見つかりませんでした。
しょうがないので、gnus-group-get-new-newsでGnusのソースを検索してみると以下の定義が見つかりました。

(defun gnus-demon-add-rescan ()
  "Add daemonic scanning of new articles from all backends."
  (gnus-demon-add-handler 'gnus-demon-scan-news 120 60))

gnus-demon-scan-newsがgnus-group-get-new-newsを実行していて、 gnus-demon-add-handlerは指定関数をタイマーに登録(指定時間毎に定期実行)していました。
なので、gnus-demon-add-rescanを実行すれば良さそうなんですが、 gnus-demon-add-rescanを実行している箇所が見つかりませんでした。
タイマー(定期実行処理)を保持していると思われる変数gnus-demon-timersの値もnilになっているので、 どうやらデフォルトでは新着メールの自動確認は行われないようです。

んじゃ、Gnus開始時に実行するようにすれば良いよね。というわけで、

(add-hook 'gnus-started-hook 'gnus-demon-add-rescan t)

として解決。・・・とはいきませんでした。。

タイマーは登録されているが・・・

上記設定により、Gnus開始後、gnus-demon-timersにgnus-demon-add-rescanを実行するタイマーは 登録されていたのですが、実行間隔が7200とか3600とかになっていました。
新着メール確認が1時間(3600秒)毎とか。どんなゆとり世代やねん。。
何故なのかとソースを見てみると、指定された時間にgnus-demon-timestepという変数の値を掛けていました。
gnus-demon-timestepはデフォルトで60になっていましたが、ややこしいので1を設定しました。

これで、1分毎に実行されるだろ!・・・とはいきませんでした。。

タイマーは1分になっているが・・・

それでもgnus-demon-scan-newsは実行されないので、edebugを以下の関数に仕掛けてデバッグしました。

(defun gnus-demon-run-callback (func &optional idle)
  "Run FUNC if Emacs has been idle for longer than IDLE seconds."
  (unless gnus-inhibit-demon
    (when (or (not idle)
              (and (eq idle t) (> (gnus-demon-idle-since) 0))
              (<= idle (gnus-demon-idle-since)))
      (with-local-quit
       (ignore-errors
         (funcall func))))))

gnus-demon-run-callbackは、タイマーが実行する関数で、引数でgnus-demon-scan-newsが渡されます。
で、第2引数のidleには

(gnus-demon-add-handler 'gnus-demon-scan-news 120 60)

と指定された場合は60が渡ってくるのですが、gnus-demon-idle-sinceが0.0を返すため、 funcallステートメント(gnus-demon-scan-news)が実行されません。

gnus-demon-idle-sinceという関数の定義は以下のようになっています。

(defun gnus-demon-idle-since ()
  "Return the number of seconds since when Emacs is idle."
  (if (featurep 'xemacs)
      (itimer-time-difference (current-time) last-command-event-time)
    (float-time (or (current-idle-time)
                    '(0 0 0)))))

私にはロジックがよく理解できなかったんですが(待機秒数を返している?)、
デバッグした限りでは、戻り値は0.0となり、idleに正の整数が渡ってくると一向にfuncallまで処理がいかないため、

(gnus-demon-add-handler 'gnus-demon-scan-news 120 nil)

上記のようにnilを指定することで、ようやくgnus-demon-scan-newsが実行されるようになりました。

gnus-demon-add-handleの指定方法

上記した通り、Gnusのソースでは第2引数、第3引数、ともに数値を指定している場合もあるので、
gnus-demon-idle-sinceが0.0以外の数値を返し、処理が実行されるケースもあるのでしょうが、
以下のように指定するのが良いのではと思われます。

; 普通のタイマーで登録する場合(Emacsの状態に関わらず定期実行)
(gnus-demon-add-handler 'gnus-demon-scan-news 120 nil)

; アイドルタイマーで登録する場合(Emacsが待機状態の時のみ定期実行)
(gnus-demon-add-handler 'gnus-demon-scan-news nil 120)

gnus-demon-add-handlerの、
第2引数が指定された場合、run-with-timerが実行され、
第2引数がnilで第3引数が指定された場合、run-with-idle-timerが実行されます。

その他

  • Emacsは、GNU Emacs 24.2.1 (i386-mingw-nt5.1.2600) of 2012-12-08 on GNUPACK です。
  • Gnusは、Gnus v5.13 です。

あとがき

何で新着メールの自動確認ごときで、こんなにてこずるのか・・・。
カスタマイズ変数設定でOKな感じにしとくのが普通じゃないの?
多機能かもしんないけど、使いにくさハンパねぇ・・・。

サマリバッファは更新されないままなので、それも何とかしたいなぁ。