如何让子 node 的 property drawer 中设置的 header-args 不要影响母 node 的 property drawer 中的非相关设置?

在 org mode 中, 子 node 中的 property drawer 中设置的 header-args 会完全取代母 node 中的 header-args 中的任何设置, 无论后者和前者有没有关系. 个人以为这并不是一个特别好的行为, 而且如果直接在子 node 中的代码块上设置 header args, 则不存在这个问题. 为了说明这一点, 下面我给出一个 org mode 的例子.

* parent node
:PROPERTIES:
:header-args: :var x=1
:END:

** block override

#+begin_src emacs-lisp :var y=2 :results verbatim
(boundp 'x)
#+end_src

#+RESULTS:
: t

** node override
:PROPERTIES:
:header-args: :var y=2 :results verbatim
:END:

#+begin_src emacs-lisp
(boundp 'x)
#+end_src

#+RESULTS:
: nil

接下来说明一下上面的 org 文件:

我在母 node parent node 的 property drawer 中设置了一个 header arg :var x=1. 那么在这个母 node 下的所有代码块默认都会知道存在变量 x.

接下来我在两个子 node, block overridenode override 中, 设置相同的 header args :var y=2 :results verbatim. 区别是: 在 node block override 中, 这些 header args 设置在代码块上; 而在 node node override 中, 同样的 header args 设置在其 node 的 property drawer 中. 在前一种情况下, 即使设置了新的变量 y, 子 node 中的代码块依然能够记得母 node 中设置的变量 x. 而在后一种情况下, 子 node 则不能记住 x.

个人推测, 代码块上设置的 header args 是直接 append 在母 node property drawer 中设置的 header args 之后的; 而子 node property drawer 中设置的 header args 则完全抹除了母 node property drawer 中设置的 header args.

我的问题是: 如何让子 node property drawer 中设置的 header args 的行为和代码块上设置的 header args 一样, 即不要抹除母 node property drawer 中设置的 header args?

后来想了一下这种设定也有它的道理. org 笔记的 node 有灵活性, 子 node 经常会被 refile, 母 node 不一定稳定. 子 node 容易失去母 node 中的设定, 所以对于记灵活笔记的人来说, 可能直接在每个 node 里把这个 node 需要的全部 header args 设置完整会方便 node 的流动.

但是这个设置有没有个变量可以开关?

hearder-args 的值是由 org-babel-params-from-properties 中的 (org-entry-get (point) "header-args" 'inherit) 获取的,具体行为参考 org-entry-get 的 doc :

Get value of PROPERTY for entry or content at point-or-marker POM.

If INHERIT is non-nil and the entry does not have the property,
then also check higher levels of the hierarchy.  

如果想要对特定的 property 特殊处理可以给 org-entry-getorg-babel-params-from-properties 加 advice 。

解决方案:

将 node node override 中的 :header-args: 改为 :header-args+: 即可. + 代表 append, 可以继续加属性, 而不是取代已有的属性.

1 个赞