在 Org-mode 语法文档的开头,它将 Org-mode 文本格式称为一种简单,但用途广泛的纯文本格式,既易于使用又能够表示复杂的文档。与 Markdown 破碎的生态相比,Org-mode 的语法非常统一。这大概是由于它内置的功能强于 Markdown 从而足以用于大多数目的,而不用像 Markdown 一样使用 HTML 标签或发明新东西。
首先,Org-mode 语法的组成可以分为对象(object)和元素(element)两类,如果以段落(paragraph)为基准,那么 元素 就是层次大于等于 段落 的组件,也就是不能被段落容纳; 对象 则是比 段落 层次小的东西,可以被段落容纳。这里的段落会在 ox-html
后端中被导出为 <p>
标签。
更进一步,元素可以从大到小分为 heading, section, greater element 和 lesser element 。元素确定了特定的语法环境,在所有元素中只有 heading, section, property drawer 和 planning line 是上下文无关的,其他的语法成分只能存在于特定的环境中。
在所有这些元素中, lesser element 不能容纳其他的元素。比如,段落可被认为是一个小元素,它的里面就不能包含另一个段落。 greater element 可以包含它们自己,以及其他的 greater element 和 lesser element 。 section 可以包含 greater element 和 lesser element , heading 可以包含 section 和其他的 heading 。
变量 org-element-all-elements
提供了完整的元素列表:
( babel-call center-block clock comment comment-block diary-sexp drawer
dynamic-block example-block export-block fixed-width footnote-definition
headline horizontal-rule inlinetask item keyword latex-environment node-property
paragraph plain-list planning property-drawer quote-block section
special-block src-block table table-row verse-block)
(length org-element-all-elements) => 30
按照语法文档的分类,上面这些元素可以分为:
- 最大的
headline
和section
,共 2 个 - greater element ,包括
center-block
,quote-block
,special-block
,drawer
,property-drawer
,dynamic-block
,footnote-definition
,inlinetask
,item
,plain-list
,table
,共 11 个 - lesser element ,包括
comment-block
,example-block
,export-block
,src-block
,verse-block
,clock
,diary-sexp
,planning
,comment
,fixed-width
,horizontal-rule
,keyword
,babel-call
,latex-environment
,node-property
,paragraph
,table-row
,共 17 个
变量 org-element-all-objects
提供了完整的对象列表:
( bold citation citation-reference code entity export-snippet footnote-reference
inline-babel-call inline-src-block italic line-break latex-fragment link macro
radio-target statistics-cookie strike-through subscript superscript table-cell
target timestamp underline verbatim)
(length org-element-all-objects) => 24
在 Org-mode 语法中,对象的分类不如元素那样细致,不过文档中给出了所谓的最小对象集合和标准对象集合,分别是:
- minimal set of objects:
plain-text
,text-markup
,entity
,latex-fragment
,subscript
,superscript
. 其中text-markup
包括bold
,italic
,underline
,verbatim
,code
和strike-through
. 共 11 个 - standard set of objects: 除了
citation
和table-cell
外的所有对象,共 22 个
Org-mode 本身最高支持无限级别的 headline
,在导出时最高的 headline
导出级别取决于 org-export-headline-levels
,它的默认值为 3
。在 ox-w3ctr
中我使用 org-w3ctr-headline-levels
覆盖了该选项,且将默认值设置为 5
,这是因为在 ox-html
中 #+TITLE
会被导出为 <H1>
标题,一级 headline
到五级 headline
分别被导出为 <H2>
到 <H6>
,这就是 HTML 支持的所有标题级别了。实际使用中我们很少会用到 3 级以上的 headline
。
以下是不同级别的 headline
例子:
在 Org-mode 中, headline
是一个无缩进的如下结构,Org-mode 语法文档中对 headline
的描述如下:
headline
由级数 STARS
,GTD 关键字 KEYWORDS
,优先级 PRIORITY
,注释标志 COMMENT
,标题内容 TITLE
和标签 TAGS
组成,除 STARS
外其他都是可选项。其中:
STARS
包含一个或多个星号*
,并带有空格字符SPC
后缀。星号的数量决定了headline
的级别。因为
headline
要求以*
开头且与行首之间不能有空格,我们也就不能直接在段落的开头使用*
。要解决在一行的开头使用*
这个问题,直接的方法是添加空格或零宽空格,不过正确做法是使用,
转义,即,*
。如果用户加载了
org-inlinetask
且*
的数量大于等于org-inlinetask-min-level
(默认值为 15),那么它会成为一个inlinetask
而不是headline
KEYWORD
为org-todo-keywords-1
中的一个字符串,它被叫做“todo keyword”标准的
org-todo-keywords-1
为("TODO" "DONE")
,即默认可用的KEYWORD
为"TODO"
和"DONE"
。读者可以参考 Org-mode 文档的 TODO Extensions 一节来扩展关键字。PRIORITY
为以#
为前缀的带中括号单字符(比如[#A]
和[#1]
),它被叫做“priority cookie”PRIORITY
可以用来记录headline
的优先级,默认情况下 Org-mode 支持[#A]
,[#B]
和[#C]
,不写PRIORITY
则默认为[#B]
优先级。优先级的使用可以参考 Priorities。COMMENT
是字符串"COMMENT"
,表示headline
被注释了,导出时该headline
会被忽略TITLE
为来自标准对象集合的对象,且不为断行对象TAGS
为一系列由:
分隔的 token,token 可包含[a-z-A-Z0-9_@#%]
TAGS
没什么好说的,需要注意的是 tag 名不能包含-
字符。TAGS
的用法可以参考 Tags。
以下是一些和 headline
操作相关的命令:
TAB(org-cycle)
,切换headline
的显示 Global and local cyclingheadline
间的移动命令 MotionC-c C-n(org-next-visible-heading)
C-c C-p(org-previous-visible-heading)
C-c C-f(org-forward-heading-same-level)
C-c C-b(org-backward-heading-same-level)
C-c C-u(outline-up-heading)
C-c C-j(org-goto)
- 作用于 headline 的编辑命令 Structure Editing
M-LEFT(org-do-promote)
,M-RIGHT(org-do-demote)
M-S-LEFT(org-promote-subtree)
,M-S-RIGHT(org-demote-subtree)
M-UP(org-move-subtree-up)
,M-DOWN(org-move-subtree-down)
- 设置
headline
的TAGS
C-c C-c(org-set-tags-command)
Setting Tags - 切换
headline
的COMMENT
状态C-;(org-toggle-comment)
- 切换
headline
的ARCHIVE
标签状态C-c C-x a(org-toggle-archive-tag)
section
包含一个或多个非 heading
元素。粗略来说, section
就是位于 headline
之间的内容。文档中给出的例子如下:
上面内容对应的 AST 为:
在第一个 headline
之前的内容构成的 section
被叫做 zeroth section ,它与普通 section
的区别在于可以直接包含 property drawer 元素,但不能含有 planning 元素,也就是说它允许如下结构:
其中 BLANK-LINES
和 COMMENT
不是必须的。
在这一节中我们会介绍所有二十八个元素,加上上面的 headline
和 section
一共三十个。
greater blocks 之所以 greater 自然是要与 lesser blocks 相对,它们允许包含其他的 greater element 。所有的(就 3 种) greater block 都具有如下结构(其中的 BEGIN
也可为小写):
其中, NAME
是不含空格的字符串,可以为任意不属于 lesser block 的名字; PARAMETERS
是可选的参数,是不含换行的字符串; CONTENTS
为不含 #+END_NAME
行的任意内容。最后一条规则也就注定了它们不能自我嵌套(不过可以相互嵌套)。这些块结构用的最多的时候也许是导出时根据不同后端生成具有相同语义的产物。
在编写 Org-mode 导出后端时,也许我们可以考虑利用这些 block
(特别是 special block
)以及它们的 PARAMETERS
参数来实现更加丰富的语义。
center-block
就是让其中内容居中的 block,不过在 Org-mode buffer 中并不会居中显示。以下是一个 center block
例子(来自 Paragraphs):
其中 \\
表示段落内换行,它的效果如下:
Everything should be made as simple as possible,
but not any simpler
类似地, quote block
具有语义上的引用义:
#+BEGIN_QUOTE
你说的对,但是《原神》是由米哈游自主研发的一款全新开放世界冒险游戏。游戏发生在一个被称作「提瓦特」的幻想世界,在这里,被神选中的人将被授予「神之眼」,导引元素之力。你将扮演一位名为「旅行者」的神秘角色,在自由的旅行中邂逅性格各异、能力独特的同伴们,和他们一起击败强敌,找回失散的亲人——同时,逐步发掘「原神」的真相。
你说得对,但是这就是奎桑提,HP 4700,护甲 329,魔抗 201 的英雄。有不可阻挡,有护盾,还能过墙。有控制,甚至冷却时间只有 1 秒,只要 15 点蓝。转换姿态时甚至可以刷新 W 的 cd,还有真实伤害。然后,护甲和魔抗提升后还能获得技能加速,缩短 Q 的 cd,还缩短释放时间,然后还有攻击力。W 就啊啊啊啊啊啊!!!
#+END_QUOTE
你说的对,但是《原神》是由米哈游自主研发的一款全新开放世界冒险游戏。游戏发生在一个被称作「提瓦特」的幻想世界,在这里,被神选中的人将被授予「神之眼」,导引元素之力。你将扮演一位名为「旅行者」的神秘角色,在自由的旅行中邂逅性格各异、能力独特的同伴们,和他们一起击败强敌,找回失散的亲人——同时,逐步发掘「原神」的真相。
你说得对,但是这就是奎桑提,HP 4700,护甲 329,魔抗 201 的英雄。有不可阻挡,有护盾,还能过墙。有控制,甚至冷却时间只有 1 秒,只要 15 点蓝。转换姿态时甚至可以刷新 W 的 cd,还有真实伤害。然后,护甲和魔抗提升后还能获得技能加速,缩短 Q 的 cd,还缩短释放时间,然后还有攻击力。W 就啊啊啊啊啊啊!!!
special block
相对特殊一些,它的 NAME
可以为任意非 lesser block
以及 quote
和 center
的名字,比如 #+begin_aside
。它的意义取决于导出后端想要赋予它什么意义:
drawer 具有如下结构:
在 Org-mode Manual 的 Drawers 一节是这样描述它的:
Sometimes you want to keep information associated with an entry, but you normally do not want to see it. For this, Org mode has drawers. They can contain anything but a headline and another drawer.
简单来说, drawer
提供了一种非 headline
的折叠展开内容方法。我们可以通过 C-c C-x d(org-inser-drawer)
插入 drawer
。当某个 region 被选中时,调用该命令会将当前 region 中的内容插入到 drawer
中;当带有前缀参时,该命令会调用 org-insert-property-drawer
来在当前 headline
插入 PROPERTIES drawer
。
如果使用 #+caption:
作为 <details>
中的 <summary>
的话, drawer
将会非常适合作为 details
的对应物,就像这样:
This is a details
Contents are hidden
#include <stdio.h>
int main(void)
{
print("hello world\n");
return 0;
}
property drawer
必须紧接着 headline
或 inlinetask
,作用是为它们提供属性信息:
相比一般 drawer
, property drawer
的要求更严格一些,它的 NAME
必须为 PROPERTIES
,而且 CONTENTS
中不能含空行,只能是 node property
。以下是一个例子:
本节的标题 property drawer
就具有一个 CUSTOM_ID
属性,读者可以查看本 HTML 页面的源代码找到它的 ID。
dynamic block
结构如下:
其中 NAME
是不含空格的字符串; PARAMETERS
是可选的参数字符串,不含换行符; CONTENTS
是除 dynamic block
外的零个或多个其他元素。
在 dynamic block
的文档 Dyanmci Block 中对参数结构有更精细的描述,它应为 :parameter1 value1 :parameter2 value2 ...
,不过也不是非得这样,使用 (org-element-property :arguments dynamic-block)
获取到的参数就是一整个字符串。
根据文档的说法, dynamic block
可以根据用户函数对块中的内容进行自动更新。我们可以通过 C-c C-x x(org-dynamic-block-insert-dblock)
来在当前位置插入 dynamic block
,并通过 C-c C-x u(org-dblock-update)
来更新块的内容。我们可以添加 org-update-all-dblocks
到某些 hook 中来在必要时触发所有 dynamic block
的更新。读者可以阅读文档以及 org-dblock-write:clocktable
来学习如何编写生成和更新 dynamic block
的函数。
footnote definition
是脚注的定义部分,它和 headline
一样必须顶格,它的结构如下:
其中 LABEL
是数字或由 [[:word:]-_]
组成的字符串,用来标识对应的脚注, CONTENTS
为脚注的内容,它在下一个 footnote definition
之前结束,或者是下一个 headline
、两个连续的换行、或 buffer 的末尾。这是一些例子,注意在第二个脚注中,隔了一行的字符串仍属于该脚注:
Org-mode 支持三种形式的脚注,具体的用法可以参考 Creating Footnotes。
下面是一段来自维基百科的内容,我改成了 Org-mode 格式:
Wikipe-tan (Japanese[fn:Japanese]: ウィキペたん) is a personification of Wikipedia[fn:Wikipedia] created in January 2006 by Japanese editor Kasuga[fn:Kasuga] She is an unofficial mascot of Wikipedia and is used at several WikiProjects. The -tan in "Wikipe-tan" is an affectionate suffix, in the form of a Japanese honorific. Like the OS-tans, she is a product of moe anthropomorphism.
[fn:Japanese] Janapanese 的 wiki 链接:https://en.wikipedia.org/wiki/Japanese_language
[fn:Wikipedia] Wikipedia 的链接:https://en.wikipedia.org/wiki/Wikipedia
[fn:Kasuga] In the aftermath of the unified login finalization, the user now going by Kasuga on Commons and on English Wikipedia is a different person. The accounts of the creator of Wikipe-tan were renamed Kasuga~enwiki, Kasuga~jawiki and Kasuga~commonswiki.
Wikipe-tan (Japanese[Japanese]: ウィキペたん) is a personification of Wikipedia[Wikipedia] created in January 2006 by Japanese editor Kasuga[Kasuga] She is an unofficial mascot of Wikipedia and is used at several WikiProjects. The -tan in "Wikipe-tan" is an affectionate suffix, in the form of a Japanese honorific. Like the OS-tans, she is a product of moe anthropomorphism.
请点击脚注链接跳转到定义部分。
除了上述标准脚注外,Org-mode 还支持匿名脚注和内联脚注,它们的导出效果如下:
当 headline
的星号数量大于等于 org-inlinetask-min-level
时,它就成了 inlinetask
,不过仅在 org-inlinetask
加载后才会有 inlinetask
。这个功能我从来没用使用过。下面是一个例子:
*************** TODO some tiny task
This is a paragraph, it lies outside the inlinetask above.
*************** TODO some small task
DEADLINE: <2009-03-30 Mon>
:PROPERTIES:
:SOMETHING: or other
:END:
And here is some extra text
*************** END
我在 Org-mode Manual 中居然没有找到 inlinetask
的章节。
item
是单个列表项,它在内部可以嵌套 item
,结构如下:
其中:
BULLET
是表头符号,对无序列表可以是*
,-
或+
注意顶格的
*
不能作为item
开头,因为它会被识别为headline
;对有序列表需要是一个数字或单个a-z
的字符加上.
或)
,比如1.
和a)
COUNTER-SET
指定有序列表的序号值,格式为[@COUNTER]
CHECK-BOX
选择框,可以为[ ]
,[X]
或[-]
TAG
格式为TAG-TEXT ::
,其中TAG-TEXT
会作为标准集合对象解析CONTENTS
为零个或多个元素,并在遇到以下情况时结束- 下一个
item
- 相比起始行具有更浅或相同缩进的行,这不计算其他非段落元素或 inlinetask 边界内的行
- 两个连续的换行
- 下一个
下面是文档中给出的例子:
- item
3. [@3] set to three
+ [-] tag :: item contents
* item, note whitespace in front
* not an item, but heading - heading takes precedence
Org-mode Manual 的 Plain Lists 一节对列表进行了更为细致的描述。上面提到的 TAG
用于生成所谓的 description list ,在 HTML 导出后端中,它会使用不同于 ol
和 ul
的标签。
这是一个无序列表例子:
- 第一项
- 第二项
- 第三项
这是一个有序列表的例子:
- いいよ,こいよ
- 伊已逝,吾亦逝
- 意易失,吾亦逝
- 逸一时,误一世
- 疑一时,误一世
- こめいじ こいし
这是一个描述性列表的例子:
- 你好
- 今日は
- 再见
- また明日
plain list
就是一系列具有相同缩进的连续 item
。文档中给出了一个 plain list
对应的 AST:
(ordered-plain-list
(item
(paragraph))
(item
(paragraph)
(descriptive-plain-list
(item
(paragraph)))))
Org-mode Manual 在 Plain Lists 一节给出了一些方便的命令,这里简单列出部分:
S-UP
S-DOWN
,移动到当前列表的下一个/上一个item
M-UP
M-DOWN
,将当前item
上移/下移一位M-LEFT
M-RIGHT
,减少/增加当前item
的缩进,不处理子item
C-c C-c
,切换Checkbox
的状态
Org-mode 支持两种表格,一种来自 Org-mode 自己,另一种来自 Emacs 的 table.el,这两种表格的性状略有不同。Org-mode 表格以 |
开头而 tabel.el 以 +-
开头。以下代码展示了两者的不同之处:
表格由一行行的 lesser element table row
组成,我们会在后文介绍它。以下是一个表格例子:
Name | Phone | Age |
---|---|---|
Peter | 1234 | 24 |
Anna | 4321 | 25 |
Org-mode 的表格功能非常强大,支持一定程度的运算功能,可以看作是“穷人的 Excel”。 table
的具体用法可以参考 Org-mode Manual 的 Tables 一章。
(从 block
开始就是 lesser block 了,因此我加粗了标题)
lesser block
具有与 greater block
相似的结构:
其中, NAME
只能为以下各小节标题其中之一, DATA
同样是一个不含断行的字符串, CONTENTS
不含 #+END_NAME
。关于各 lesser block
的文档如下列表所示:
comment block
即注释块。在导出时它们不会被导出。
example block
通常用于显示代码或文字的样例,它会保留原始样式,包括空格和换行,以便准确显示内容。
我们可以通过 export block
指定一段内容针对特定导出后端的内容,这允许在同一文档中为不同的导出格式定制内容。对 HTML 后端来说,我们可以有如下做法:
以下代码可以导出颜色为红色的 hello world
:
src block
算是 Org-mode 的重量级特性,在 Org-mode Manual 中专门有一章介绍它的用法。在 src block
中, DATA
的格式如下:
其中 LANGUAGE
是源代码块的语言,为一无空格字符串; SWITCHES
是由空格分隔的任意数量 SWITCH
模式;最后的 ARGUMENTS
为无折行字符串。其中 SWITCH
的写法可以参考上面给出的 Literal Examples 文档,而 ARGUMENTS
参数可以参考 Using Header Arguments。
和导出相关的 ARGUMENTS
为 :exports
,可以指定 code
, results
, both
和 none
四种选项。其中 code
为默认选项,即导出代码, results
为导出代码的执行结果, both
为导出两者, none
则不导出代码块。
以下是一个 src block
例子:
#+begin_src emacs-lisp
"This string
* has "*" escaped.
Otherwise, '* has "*" escaped.' would be treated as a heading (which
is context-free)."
"#+ lines may or may not need to be escaped:
#+end_src if not escaped, would be this source block.
However,
#+keyword: does not interfere with code block end and may be left as is.
#+keyword may be escaped as well, optionally - parser removes all the
commas in ,* and ,#+ lines."
#+end_src
我们可以使用 org-export-use-babel
来控制代码导出时是否使用 babel 处理代码,我发现设置它为 nil
能缩短不少的时间,因此我用 org-w3ctr-use-babel
覆盖了这个选项,并设置其默认值为 nil
。
verse block
的功能非常简单,就是保持文本的结构,但它没有 example block
那么强,除了换行和缩进外它不会改变其他对象的格式。在以下例子中,若代码块环境为 example
,那么 =
内容在 HTML 导出中会直接显示等于号,而不是生成 <code>
标签:
#+BEGIN_VERSE
Great clouds overhead
Tiny black birds rise and fall
Snow covers Emacs
---AlexSchroeder, =hello=
#+END_VERSE
Great clouds overhead
Tiny black birds rise and fall
Snow covers Emacs
—AlexSchroeder, hello
clock
元素的形状如下:
其中的 INACTIVE-TIMESTAMP
和 INACTIVE-TIMESTAMP-RANGE
都是 timestamp
对象(下文会介绍)。 DURATION
的格式为 HH:MM
。一个简单的例子如下:
diary sexp
是一个无缩进的如下结构:
例子如下:
diary-sexp
的具体用法可以参考 Sexp Entries and the Fancy Diary Display。
planning
元素具有如下结构:
其中 PALNNING
一行包含一个或多个 KEYWORD: TIMESTAMP
模式, KEYWORD
可为 DEADLINE
, SCHEDULED
或 CLOSED
, TIMESTAMP
为一个 timestamp
对象。 planning
必须紧随 heading
,两者之间不能有空行。
文档给出的例子如下:
除了上面提到的 comment block
,Org-mode 也支持单行注释,只需要一个顶格 #
加上空格即可:
自然,注释是不会导出的。
以 :
加空格开头的行将成为单行 example block
,不过在 ox-html
中我们无法通过 attr_html
为其添加其他 HTML 属性。
This is a fixed width.
如果一行以 -
开头且至少有 5 个连续的 -
符号,那么它会成为一个 horizontal rule
,在 ox-html
中它导出为 <hr>
标签,在 ox-w3ctr
中同样也是。
keywords
的形式如下:
其中:
KEY
- 一个除
call
外含无空格字符的字符串 VALUE
- 不含换行符的任意字符串
当 KEY
是 org-element-parsed-keywords
中的任一成员时, VALUE
可以包含除 footnote reference
的任意标准对象(第一节提到的标准对象集合)。 org-element-parsed-keywords
的值如下所示:
在 ox-html
中, org-html-keyword
实现为可以导出 HTML
和 TOC
关键字,前者用于导出 HTML
代码片段,后者用于导出局部目录。
如果 KEY
为 call
那么 keywords
就是 babel call
,它具有以下几种可能的形式:
#+call: NAME(ARGUMENTS)
#+call: NAME[HEADER1](ARGUMENTS)
#+call: NAME(ARGUMENTS)[HEADER2]
#+call: NAME[HEADER1](ARGUMENTS)[HEADER2]
其中, NAME
是不含换行符和 []()
的任意字符串; ARGUMENTS
是可选的参数,包含任意非换行符字符,不过开括号和回括号必须配平; HEADER1
和 HEADER2
是可选的参数,同样它们由非换行符组成,且要求括号配平。
我几乎没有使用过 Org-mode 的 babel 功能,此处不详细展开。
所谓的 affiliated keyword
(关联关键字)可以依附于某个元素来提供一些额外的信息,比如 #+attr_html
可以为某个元素提供一些 HTML
属性。 affiliated keywords
具有如下结构:
其中, KEY
是一个位于 org-element-affiliated-keywords
中的成员; BACKEND
是一个由 [a-zA-Z0-9-_]
组成的字符串,对 HTML
后端就是 html
; OPTVAL
是不含换行符的字符串,且括号必须配平,它仅在 KEY
属于 org-element-dual-keywords
时有效; VALUE
是不含换行符的字符串,不过当 KEY
属于 org-element-parsed-keywords
时有例外可以换行。
org-element-affiliated-keyword
给出了可用的 affiliated 关键字:
(defconst org-element-affiliated-keywords
'("CAPTION" "DATA" "HEADER" "HEADERS" "LABEL" "NAME" "PLOT" "RESNAME" "RESULT"
"RESULTS" "SOURCE" "SRCNAME" "TBLNAME"))
(defconst org-element-dual-keywords '("CAPTION" "RESULTS")
"List of affiliated keywords which can have a secondary value.
In Org syntax, they can be written with optional square brackets
before the colons. For example, RESULTS keyword can be
associated to a hash value with the following:
#+RESULTS[hash-string]: some-source
This list is checked after translations have been applied. See
`org-element-keyword-translation-alist'.")
需要注意的是,某些关键字已经过时了:
(defconst org-element-keyword-translation-alist
'(("DATA" . "NAME") ("LABEL" . "NAME") ("RESNAME" . "NAME")
("SOURCE" . "NAME") ("SRCNAME" . "NAME") ("TBLNAME" . "NAME")
("RESULT" . "RESULTS") ("HEADERS" . "HEADER")))
根据翻译表,现在推荐使用的 affiliated 关键字有:
- CAPTION (dual)
- NAME
- HEADER
- PLOT
- RESULTS (dual)
除了 comments
, clocks
, headings
, inlinetasks
, items
, node properties
, planning
, property drawers
, sections
和 table rows
外,其他的元素都可以被赋予 affiliated keyword
。
在一个元素上重复使用某个 affiliated keyword
将会导致先前的值被最后一个值覆盖。唯一的例外是 header
:
The sole exception to this is
#+header
: keywords, where in the case of multiple:opt val
declarations the last declaration on the first line it occurs on has priority.唯一的例外是
#+header:
关键字,在存在多个:opt val
声明的情况下,优先考虑首次出现的行上的最后一个声明。
此外,如果 KEY
属于 org-element-dual-keywords
或 KEY
为 #+attr_BACKEND
,那么多个 VALUE
会被连接起来得到最终的 VALUE
。文档给出了这样的例子:
latex environment
具有以下结构:
其中, NAME
是一个包含字母数字或 *
的字符串, EXTRA
是不含 \end{NAME}
内容的字符串, CONTENTS
是不含 \end{NAME}
的字符串。以下是一个简单的例子:
node property
只能存在于 property drawer
中,它具有如下结构:
其中, NAME
是不含空白字符且不以 +
结尾的字符串, VALUE
是不含换行符的字符串。
和 babel call 一样,我基本上没有用过。
paragraph
是默认的元素,空行和其他元素会终止段落。
table row
由 |
跟着以下情况组成:
- 任意数量的
table cell
- 一个
-
,表示这是一行“规则”行
table row
只能存在于 table
中。
对象可以出现在以下元素中:
keyword
的VALUES
中,要求KEY
属于org-element-parsed-keywords
headline
的TITLE
inlinetask
的TTILE
item
的TAG
clock
的INACTIVE-TIMESTAMP
和INACTIVE-TIMESTAMP-RANGE
,不过只能包含 inactive timestampplanning
的TIMESTAMP
,只能是 timestampparagraph
table cell
table row
,只能是table cell
对象verse block
在 Org-mode 中, entity
具有如下结构:
其中, NAME
是一个存在于 org-entities
或 org-entities-user
alist 中的键; POST
是一个非字母(non-alphabetic)字符, SPACES
是一个或多个空格。以下是文档给出的例子:
1¢. 1.5em space: here, all three spaces in = = constitute the entity name.
org-entities
和 org-entities-user
的值分别如下:
org-entities =>
("* Letters" "** Latin" ("Agrave" "\\`{A}" nil "À" "A" "À" "À")
("agrave" "\\`{a}" nil "à" "a" "à" "à") ("Aacute" "\\'{A}" nil "Á" "A" "Á" "Á")
("aacute" "\\'{a}" nil "á" "a" "á" "á") ("Acirc" "\\^{A}" nil "Â" "A" "Â" "Â")
("acirc" "\\^{a}" nil "â" "a" "â" "â") ("Amacr" "\\={A}" nil "Ā" "A" "Ã" "Ã")
("amacr" "\\={a}" nil "ā" "a" "ã" "ã") ("Atilde" "\\~{A}" nil "Ã" "A" "Ã" "Ã")
("atilde" "\\~{a}" nil "ã" "a" "ã" "ã") ...)
(length org-entities) => 435
org-entities-user => nil
在 Org-mode 语法文档的附录给出了完整的 entry 列表,这里用几个可能比较常用的作为示例:
\alpha \beta \gamma \delta \epsion \eta \theta \lambda \pi \phi \omega \dots \laquo \raquo \lsaquo \rsaquo \vert \S \copy \trade \pm \times \div \frac12
\larr \lArr \uarr \uArr \rarr \rArr \darr \dArr \harr \hArr \crarr \oplus \otimes \check
α β γ δ \epsion η θ λ π φ ω … « » ‹ › | § © ™ ± × ÷ ½
← ⇐ ↑ ⇑ → ⇒ ↓ ⇓ ↔ ⇔ ↵ ⊕ ⊗ ✓
我们也可以直接使用 C-x 8 RET
来选择并输入 Unicode 字符。
LaTex fragment
具有如下结构:
其中, NAME
是不存在于 org-entites
和 org-entites-user
alist 的字符串, BRACKETS
是以下结构,它与 NAME
间不能存在空格:
CONTENTS1
不能包含 {}[]
和换行符, CONTENTS2
不能包含 {}
和换行符。以下是一些例子:
但是,这种 LaTeX fragment
似乎在 LaTeX 后端会更加有用,在 HTML 后端中它们保持了原样。
对于第二种和第三种 LaTeX fragment
, CONTENTS
是可以包含任意字符的字符串,不过第二种不能包含 \)
,第三种不能包含 \]
,以下是两个简单的例子:
\[\left(\begin{matrix}y_0\\y_1\\y_2\\\vdots\\y_{N-1}\end{matrix}\right) = \left(\begin{matrix}1&1&1&\dots&1\\1&W_N^1&W_N^2&\dots&W_N^{N-1}\\1&W_N^2&W_N^4&\dots&W_N^{2(N-1)}\\\vdots&\vdots&\vdots&\cdots&\vdots\\1&W_N^{N-1}&W_N^{2(N-1)}&\dots&W_N^{(N-1)^2}\end{matrix}\right) \left(\begin{matrix}x_0\\x_1\\x_2\\\vdots\\x_{N-1}\end{matrix}\right)\]
\(x_n = \frac1N \sum\limits_{k=0}^{N-1}e^{2\pi ik\frac nN}y_k \quad (n=0, 1, 2, \dots, N-1)\)
\[\left(\begin{matrix}y_0\\y_1\\y_2\\\vdots\\y_{N-1}\end{matrix}\right) = \left(\begin{matrix}1&1&1&\dots&1\\1&W_N^1&W_N^2&\dots&W_N^{N-1}\\1&W_N^2&W_N^4&\dots&W_N^{2(N-1)}\\\vdots&\vdots&\vdots&\cdots&\vdots\\1&W_N^{N-1}&W_N^{2(N-1)}&\dots&W_N^{(N-1)^2}\end{matrix}\right) \left(\begin{matrix}x_0\\x_1\\x_2\\\vdots\\x_{N-1}\end{matrix}\right)\]
\(x_n = \frac1N \sum\limits_{k=0}^{N-1}e^{2\pi ik\frac nN}y_k \quad (n=0, 1, 2, \dots, N-1)\)
除了上面几种形式,Org-mode 也支持 TeX 风格的 LaTeX fragment
:
其中:
- PRE
- 一行的开头或任意非
$
符号的字符 - CHAR
- 不是
.,?;"
的非空白字符 - POST
- 任何标点符号(包括括号和引号)、空格字符或行尾
- BORDER1
- 不是
.,;$
的非空白字符 - BODY
- 不含
$
的任意字符串 - BORDER2
- 不是
.,;$
的非空白字符
export snippet
具有如下结构:
其中 BACKEND
是某导出后端的名字, VALUE
是不含 @@
的任意字符串。简单的例子如下:
我是插入标签 我是删除标签
footnote reference
具有如下结构:
其中, LABEL
是一个不含空格的字符串,可包含 -_
; DEFINITION
是标准对象,我们已经在 footnote definition
对这种对象进行了简单的举例,此处不再赘述。
citation
具有如下结构:
[cite CITESTYLE: REFERENCES]
[cite CITESTYLE: GLOBALPREFIX;REFERENCES]
[cite CITESTYLE: REFERENCES;GLOBALSUFFIX]
[cite CITESTYLE: GLOBALPREFIX;REFERENCES;GLOBALSUFFIX]
文档中给出了如下例子:
ox-html
没有导出 citation
。
citation reference
只能存在于 citation
中,且具有如下结构:
文档给出了如下例子:
[cite:@key]
[cite/t:see;@foo p. 7;@bar pp. 4;by foo]
[cite/a/f:c.f.;the very important @@atkey @ once;the crucial @baz vol. 3]
同样, ox-html
不导出 citation reference
。
inline babel call
具有如下结构:
call_NAME(ARGUMENTS)
call_NAME[HEADER1](ARGUMENTS)
call_NAME(ARGUMENTS)[HEADER2]
call_NAME[HEADER1](ARGUMENTS)[HEADER2]
其中, NAME
是包含除 []()
字符外任意字符的字符串, ARGUMENTS
, HEADER1
和 HEADER2
是不含换行符的字符串,且括号必须配平。
inline source block
具有如下结构:
其中, LANG
是不含空格和 [{
的字符串,表示块中的语言; HEADERS
和 BODY
是不含换行符的字符串, HEADER
中的方括号要求配平, BODY
中的大括号要求配平。
以下是一段简单的 C 代码例子:
int a = 114514; printf("%d\n", a);
line break
即换行符,它具有以下结构:
其中, PRE
是除 \
外的任意东西, SPACE
是 0 个或多个 TAB
或 SPACE
字符。以下是一个简单的例子:
1
2
3
在 ox-html
中, line break
实现为 <br>
标签。
在 Org-mode 中 link 的种类很多,包括 radio
, angle
, plain
和 regular
。
radio link
具有如下结构:
其中 PRE
是非字母字符, RADIO
是一个或多个由 radio target
匹配的对象,它只能是最小对象(见第一节对最小对象的描述), POST
是非字母字符。下面是一个简单的例子:
This is some <<<*important* information>>> which we refer to lots.
Make sure you remember the *important* information.
This is some important information which we refer to lots. Make sure you remember the important information. 读者可打开 HTML 源代码查看链接及标签的 id 属性。
在 ox-html
中,若 :html-prefer-user-labels
在导出过程中的值非 nil
,那么 radio target
的 id 会使用它的字符串内容,但是标准 HTML id 要求满足 [a-zA-Z][a-zA-Z0-9-_]*
正则匹配,生成的 id 可能不合规范。
plain link
具有如下结构:
其中, PRE
是一个不组成 word 的字符, LINKTYPE
是 org-link-parameters
中的一种链接类型, PATHPLAIN
是链接, POST
和 PRE
同理。以下是一个简单的例子:
Be sure to look at https://orgmode.org.
angle link
可以用来消除 plain link
与周围文本的歧义,具有如下结构:
其中的 LINKTYPE
和 PATHANGLE
和 plain link
具有相同含义。我几乎从来没有使用过它。
regular link
具有以下两种形式:
其中, PATHREG
可以是以下形式:
FILENAME ("file" type)
LINKTYPE:PATHINNER ("LINKTYPE" type)
LINKTYPE://PATHINNER ("LINKTYPE" type)
id:ID ("id" type)
#CUSTOM-ID ("custom-id" type)
(CODEREF) ("coderef" type)
FUZZY ("fuzzy" type)
以下是一些例子:
macro
调用具有以下两种形式:
其中, NAME
是宏的名字,满足正则 [a-zA-Z0-9-_]
, ARGUMENTS
是宏参数。以下是一些例子:
target
具有如下形式:
其中 TARGET
不能包含 <>
和换行符,且不能以空白字符起始或结尾。
radio target
具有以下形式:
其中的 CONTENTS
必须来自最小对象集合,且不含 <>
和换行符。
以下是 target
和 radio target
的两个简单例子,读者可以打开 HTML 源代码查看其 id 以及标签:
statistics cookie
具有如下结构:
它可以用来统计完成情况,比如如下列表:
- Hello
[2/3]
[66%]
- ☑ one
- ☑ two
- ☐ three
在 ox-html
中它实现为 <code>
标签包围的文本。
subscript
和 superscript
的结构如下:
其中 CHAR
为任意非空格字符, SCRIPT
可以是如下情况:
- 单个
*
号 - 使用大括号包围的表达式,表达式本身应该是大括号配平的,且属于标准对象集合
如下形式:
其中
SIGN
可以是+
或-
或空字符串,CHARS
由任意数量的[a-zA-Z0-9]
,,
,\
和.
组成,FINAL
是一个[a-zA-Z0-9]
字符
table cell
为如下形式:
其中 CONTENTS
不能包含 |
字符,且必须只能包含最小对象集合内的对象加上 citation
, export snippet
, footnote reference
, link
, macro
, radio target
, target
和 timestamp
。
timestamp
可以是如下形式:
<%%(SEXP)> (diary)
<DATE TIME REPEATER-OR-DELAY> (active)
[DATE TIME REPEATER-OR-DELAY] (inactive)
<DATE TIME REPEATER-OR-DELAY>--<DATE TIME REPEATER-OR-DELAY> (active range)
<DATE TIME-TIME REPEATER-OR-DELAY> (active range)
[DATE TIME REPEATER-OR-DELAY]--[DATE TIME REPEATER-OR-DELAY] (inactive range)
[DATE TIME-TIME REPEATER-OR-DELAY] (inactive range)
*
, a bold object, 粗体/
, an italic object, 斜体_
, an underline object, 下划线=
, a verbatim object,引述
~
, a code object,代码
+
, a strike-through object.删除线
什么对象也不是的对象就是 plain text
。
本文差不多就是把 Org-mode 的语法文档翻译了一下,想要查看更加严谨描述的同学可以看看原文去。我在今年 4 月份写完了 ox-w3ctr
这个 Org-mode 的导出后端以及这篇测试文档,现在总算是有时间改改之前的代码,顺便加加文档了。