1 问题描述
一篇博客文章除了标题、正文,还有一些辅助信息,比如:日期,分类,字数等。使用原生 org-mode 生成的 html 不会自动生成这些内容。于是想hack一下,折腾后效果例如: [ 分类: 博客 / 日期: 2020-02-21 / 字数: 1019 ]
。
2 Org宏替代
这里主要使用了orgMode的 Macro Replacement 功能。我们可以在org文件开头定义宏,然后在正文需要的位置调用宏就可以实现辅助信息的插入。
例如,定义如下宏:
#+MACRO: poem Rose is $1, violet's $2. Life's ordered: Org assists you.
其中,"poem" 为宏的名称,后面的内容为宏的内容,"$1,$2" 为参数。然后在合适的位置调用宏:
{{{poem(red,blue)}}}
最终的结果是在调用宏的位置插入文本 "Rose is red, violet's blue. Life's ordered: Org assists you."。相信这种功能也不难理解,类似于函数的定义与调用。
除了插入一串字符,预先在org文件开头定义的一些 keyword 可以直接调用。也可以在宏中调用elisp函数,实现更为复杂的功能。辅助信息的生成就依赖这两个功能。
3 具体实现
为了实现上面的效果,我在文章开头插入了如下的宏调用:
#+begin_center [ 分类: {{{keyword(category)}}} / 日期: {{{date}}} / 字数: {{{wc}}} ] #+end_center
其中 {{{date}}}
直接调用了 #+DATE:
预定义的日期, {{{keyword(category)}}}
调用了 #+CATEGORY:
预定义的分类。这里要说明的是,对于 org-mode 已有的 keyword,如 "TITLE, AUTHOR, DATE" 这些可以直接调用。自定义的 keyword 如 "CATEGORY" 需要定义为形如 {{{keyword(category)}}}
的格式。最后,文章的字数需要使用一个 elisp 函数统计,这里需要定义一个统计字数的宏:
#+MACRO: wc (eval (gk-word-count))
不难理解,这个宏执行了 gk-word-count
这个函数,然后将返回值插入到“字数: ”后面。这个统计字数的函数定义在这里。
OK,这样每次在org发布项目的时候就会自动添加日期、分类和统计字数了。但是,每次在写文章的时候都要在开头加上 这一段内容 实在是麻烦。可以将这些内容放在单独的文件中,然后用 #+INCLUDE:
引入。
我将它们放在 post-info.org
这个文件中,完整的内容是:
#+MACRO: wc (eval (gk-word-count)) #+begin_center [ 分类: {{{keyword(category)}}} / 日期: {{{date}}} / 字数: {{{wc}}} ] #+end_center
然后在文章开头加上 #+INCLUDE: "<RELATIVE/DIRECTORY/TO>/post-info.org"
即可。
4 使用注意
如果宏定义中执行的函数需要参数,参数必须是字符串类型。比如参数中传入一个list,这个list就变成了字符串。在函数执行前需要先 (read <list>)
将字符串转为列表。