AndroidのMobileOrgを今ひとつ活用できていない理由はorg-mobile-pushを忘れるからなのである。なので、書き換えたら自動的にpushするようにしてみた。
;;; org-agenda-filesに該当するファイルをセーブしたときは、
;;; 一定時間後かEmacs終了時に自動的にorg-mobile-pushを実行する。
(setq my-org-mobile-push-timer-id nil)
(defun my-org-mobile-push-schedule ()
(my-org-mobile-push-cancel)
(setq my-org-mobile-push-timer-id
(run-at-time "1 min" nil 'my-org-mobile-push))
(add-hook 'kill-emacs-hook 'my-org-mobile-push)
)
(defun my-org-mobile-push-cancel ()
(if my-org-mobile-push-timer-id
(progn
(cancel-timer my-org-mobile-push-timer-id)
(setq my-org-mobile-push-timer-id nil)))
(remove-hook 'kill-emacs-hook 'my-org-mobile-push)
)
(defun my-org-mobile-push ()
(my-org-mobile-push-cancel) ;org-mobile-pre-push-hookをフックしているから不要なんだけど、一応。
(org-mobile-push))
;; セーブ時に自動pushをスケジュールする。
(add-hook 'org-mode-hook
;; NOTE: org-mode-hookが呼ばれるときに
;; (org-agenda-files)を使った判定を行うとなぜか終了時
;; にorg-mobile-pushが失敗する。仕方ないので判定は
;; after-save-hook呼び出し時点で行っている。
#'(lambda ()
(add-hook 'after-save-hook
#'(lambda ()
(if (member (expand-file-name (buffer-file-name)) (mapcar 'expand-file-name (org-agenda-files)))
(my-org-mobile-push-schedule)))
nil t)
))
;; 手動でorg-mobile-pushしたときは自動pushを行わないようにする。
(add-hook 'org-mobile-pre-push-hook #'(lambda ()
(my-org-mobile-push-cancel)))
最も単純な方法では、(add-hook 'kill-emacs-hook 'org-mobile-push)だけで十分なのだけど、これだとEmacs終了時に必ずorg-mobile-pushを実行するので終了が遅くなってしまう。
既存のものが何かないかなと探したらorg-mode+MobileOrg(+Dropbox)でGTD始めました。オレオレ改造をごっそり公開 - ヒルズで働くholidays-lの技ログに終了時にファイルのタイムスタンプを見てorg-mobile-pushを実行するかどうか判定するコードが掲載されていた。しかし、customでorg-mobile-directoryを設定していると変数org-mobile-directoryがpushやpullをするまで有効にならなかったり、org-mode使うまで関数org-agenda-filesが有効にならなかったり、そのままではうまく動かなかった。
上の実装ではorg-agenda-filesに該当するファイルをセーブしたときに、一定時間後または終了時にpushするようにしている。一定時間以内に何回もセーブした場合は最後にセーブした時点から一定時間後にpushする。また、手動でpushしたときは一定時間後のpushをキャンセルする。
Emacs以外から書き換えた場合などを考慮すると、タイムスタンプを見る方式の方がいいのだろうけど、まあいいや。