Emacs is a lifestyle :-)
And happy hacking emacs!

Emacs Hack - "Org宏替代" 生成文章辅助信息

分类: 博客 · 字数: 758 · ...

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>) 将字符串转为列表。