乍听之下,不无道理;仔细揣摩,胡说八道

0%

弥补org-refile的不足

“实战Elisp”系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。

GTD的第一条原则是“搜集”,为此我有一个inbox.org文件,专门记录所有的新想法、新任务。我会在每晚的固定时间处理其中的内容——有些可以马上开始做并做完,更多的则是移动到其它.org文件中,等待排期。

org-mode有一个内置的快捷键C-c C-w,专门完成将条目(org-mode的术语,即.org文件中带星号前缀的一行,参见An Explanation of Basic Org-Mode Concepts)移动到其它.org文件的需求,但它有一个缺陷——不能把条目移动到其它.org文件的顶层,而这是我经常需要做的。

为了移动到顶层,需要:

  1. 使用org-cut-subtree命令剪切当前条目(其实还会包括条目的子节点,但inbox.org中的条目基本上都没有子节点);
  2. 打开目标的.org文件;
  3. 将光标定位到文件末尾;
  4. 使用org-paste-subtree命令粘贴条目。

为了轻松完成上述四个步骤,org-refile-to-eof函数应运而生。

org-refile-to-eof函数

废话不多说,直接亮相吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
;;; 定义一个Helm的source,以便选择要粘贴的.org文件
(defvar *org-refile-eof--helm-source* nil
"用于提供目标.org文件下拉菜单的来源")

;;; 将当前条目剪切并粘贴到某个目标.org文件的末尾
(defun org-refile-to-eof ()
"将当前条目剪切到一个.org文件的末尾。"
(interactive)
;; 先调用Helm获取目标.org文件。这里需要处理没有选中任何文件的情况
(let ((path (helm :sources '(*org-refile-eof--helm-source*))))
(when path
(org-cut-subtree)
(save-excursion
;; 打开选中的文件的buffer,并移动到最后
(find-file path)
(end-of-buffer)
;; 调用org-paste-subtree粘贴进去
(org-paste-subtree)))))

变量*org-refile-eof--helm-source*定义了helm函数所要求的下拉列表名称、选项,以及选中后的处理逻辑(Helm的使用可以从How to write helm extension入门)。在我的环境中,它的值是

1
2
3
4
5
(setq *org-refile-eof--helm-source*
'((name . "refile到下列的哪个文件")
(candidates . org-agenda-files)
(action . (lambda (candidate)
candidate))))

现在,只需要敲入M-: org-refile-to-eof RET便能轻松完成之前繁琐的四个步骤。

后记

如果有迫切需求的话,我会考虑将org-refile(也就是C-c C-w对应的命令)和org-refile-to-eof合并在一起。例如,按下C-c C-w时调用的是org-refile,而按下C-u C-c C-w时调用的则是org-refile-to-eof,想想也有点小激动呢。

Liutos wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
你的一点心意,我的十分动力。