2011-08-21 ,

org-modeで自動的にpushする

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以外から書き換えた場合などを考慮すると、タイムスタンプを見る方式の方がいいのだろうけど、まあいいや。