緣由
org-mode是一個Emacs內置的major mode,當打開一個後綴爲.org
的文件時就會被啓用。在官網的介紹中提到,它可以用於管理待辦事項,而這也正是我目前使用org-mode最多的場合。比如,我用它來記錄漫畫的閱讀進度,每一話或每一章就是一個標記了TODO關鍵字的條目,讀完那一話或那一章後就會將對應的條目標記爲DONE。一般我會一週一次地歸檔自己標記爲DONE的條目,但由於一次要處理的條目可能很多,逐一將它們歸檔比較繁瑣,因此,便打算二次開發實現一個自動歸檔的功能。
需要事先聲明的是,本文不是org-mode的入門教程,也不會講解如何配置org-mode。對這方面有興趣的讀者,可以自己搜索一番,資料還是相當豐富的。
菜譜
對於每一個被完成的單獨的閱讀任務,我的做法是將其internal archive。等到一整本漫畫都讀完之後,再將整個以漫畫名命名的條目歸檔到別的文件中去。要實現自動的internal archive,最簡單直接的辦法是藉助於org-mode提供的各種hook。
org-mode提供了許多的hook,在官方的文檔中有一一列舉 。其中,名爲org-after-todo-state-change-hook
的便是我所需要的鉤子。只需往這個變量所綁定的列表中添加一個函數,那麼這個函數便會在條目切換狀態時(比如從TODO切換到DONE)被org-mode調用。
最終的ELisp代碼如下
(defun lt-archive-if-manga ()
(let ((state org-state))
(when (string= state "DONE")
(let ((tags (org-get-tags-at)))
(when (member "漫畫" tags)
(org-toggle-archive-tag))))))
(add-to-list 'org-after-todo-state-change-hook 'lt-archive-if-manga t)
稍微解釋一下。從C-h v org-after-todo-state-change-hook RET
的文檔可以得知,條目的新狀態可以通過變量org-state
獲取。取得新狀態(是個字符串)後,首先檢查其是否爲"DONE"
。如果是,再檢查這個條目是否爲一個閱讀漫畫的任務。
在我的用法中,凡是漫畫條目,都打上了名爲"漫畫"
的標籤。因此,使用函數org-get-tags-at
取得一個條目的所有標籤(包括從父級條目繼承下來的),再用member
函數判斷這些標籤中是否包含字符串"漫畫"
。如果有,就調用org-toggle-archive-tag
將該條目internal archive。
傳給函數add-to-list
的第三個參數t
的作用,是讓這個新加入鉤子的函數最後被調用。
全文完