ZMonster's Blog 巧者劳而智者忧,无能者无所求,饱食而遨游,泛若不系之舟

org-mode导出项目时发布所有文件而不只是被修改的文件

问题

使用org-mode,可以将一个目录下的所有org文件作为一个完整的项目进行导出,这个功能常常用于将写好的org文件以完整的网站结构导出成html文件。

在这个过程中,有时候我们修改了项目的设置,比如说在 org-publish-project-alist 中修改了 html-preamblehtml-postamble 两个设置——这两个参数定义了项目中所有org文件导出成html时的模板。但如果修改后执行 org-publish-project ,这个改变并不会被应用,因为org-mode导出项目时会检查项目中的文件,然后仅发布被修改或未被发布过的文件。这就是本文要解决的问题。

解决方法

上述所说的org的特性——导出项目时仅对修改过或未被发布过的文件,是由org内置的变量 org-publish-use-timestamps-flag 来决定的。

通过快捷键 C-h v 查看该变量的文档,可以看到它的描述是:

org-publish-use-timestamps-flag is a variable defined in 'ox-publish.el'. Its value is t

Documentation: Non-nil means use timestamp checking to publish only changed files. When nil, do no timestamp checking and always publish all files.

根据文档,将这个变量设置为 nil 就可以改变上述org在导出项目时的行为,但是注意 always 这个词。如果在配置中将这个变量的值设置为了 nil ,那么每次导出项目时,所有文件都会被重新发布!而我们需要的是在 "需要的时候" 重新发布所有文件,每次都重新发布会带来不必要的时间消耗,这不是我们想要的。

我的解决办法是将 org-publish-project 这个命令包装成 publish-project ,每当这个命令执行时,它会询问是否要重新发布所有文件,如果是则将 org-publish-use-timestamps-flag 这个变量置为 nil ,待发布完后又重新设回 t

下面是我的实现方法:

(defun publish-project (project no-cache)
   (interactive "sName of project: \nsNo-cache?[y/n] ")
      (if (or (string= no-cache "y")
          (string= no-cache "Y"))
          (setq org-publish-use-timestamps-flag nil))
   (org-publish-project project)
   (setq org-publish-use-timestamps-flag t))

我将这个函数绑定到了 C-x p 这个快捷键上。